From 1b9d5b33342c137fd10eecbce99281bd7b222b58 Mon Sep 17 00:00:00 2001 From: Shuanglei Tao Date: Sun, 27 Apr 2025 14:02:13 +0800 Subject: [PATCH] add GUI emulator --- .github/workflows/build.yml | 21 ++- .gitignore | 1 + EPD/EPD_service.c | 11 +- EPD/UC8176.c | 1 + GUI/GUI.c | 36 ++--- GUI/GUI.h | 18 ++- Makefile.win32 | 18 +++ README.md | 21 +++ docs/images/4.jpg | Bin 0 -> 53345 bytes emulator.c | 262 ++++++++++++++++++++++++++++++++++++ 10 files changed, 361 insertions(+), 28 deletions(-) create mode 100644 Makefile.win32 create mode 100644 docs/images/4.jpg create mode 100644 emulator.c diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0fee6d0..9d48761 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,4 +48,23 @@ jobs: name: nrf52811_xxaa path: | _build/nrf52811_xxaa.hex - SDK/17.1.0_ddde560/components/softdevice/s112/hex/s112_nrf52_7.2.0_softdevice.hex \ No newline at end of file + SDK/17.1.0_ddde560/components/softdevice/s112/hex/s112_nrf52_7.2.0_softdevice.hex + + win32: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install MSYS2 + uses: msys2/setup-msys2@v2 + with: + update: true + install: >- + make + mingw-w64-x86_64-gcc + - name: Build + run: make -f Makefile.win32 + - uses: actions/upload-artifact@v4 + with: + name: emulator + path: emulator.exe \ No newline at end of file diff --git a/.gitignore b/.gitignore index 508e75f..687667d 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ *.obj *.o *.sbr +*.exe # Build files # define exception below if needed diff --git a/EPD/EPD_service.c b/EPD/EPD_service.c index efdd5d1..0e64aa4 100644 --- a/EPD/EPD_service.c +++ b/EPD/EPD_service.c @@ -43,7 +43,16 @@ static void epd_gui_update(void * p_event_data, uint16_t event_size) EPD_GPIO_Init(); epd_model_t *epd = epd_init((epd_model_id_t)p_epd->config.model_id); - DrawGUI(epd, event->timestamp, p_epd->display_mode); + gui_data_t data = { + .bwr = epd->bwr, + .width = epd->width, + .height = epd->height, + .timestamp = event->timestamp, + .temperature = epd->drv->read_temp(), + .voltage = EPD_ReadVoltage(), + }; + DrawGUI(&data, epd->drv->write_image, p_epd->display_mode); + epd->drv->refresh(); EPD_GPIO_Uninit(); } diff --git a/EPD/UC8176.c b/EPD/UC8176.c index d8d24c7..18f2c7e 100644 --- a/EPD/UC8176.c +++ b/EPD/UC8176.c @@ -77,6 +77,7 @@ static void UC8176_PowerOff(void) int8_t UC8176_Read_Temp(void) { EPD_WriteCommand(CMD_TSC); + UC8176_WaitBusy(100); return (int8_t) EPD_ReadByte(); } diff --git a/GUI/GUI.c b/GUI/GUI.c index 38d0629..b7db204 100644 --- a/GUI/GUI.c +++ b/GUI/GUI.c @@ -1,12 +1,8 @@ -#include "Adafruit_GFX.h" #include "fonts.h" #include "Lunar.h" #include "GUI.h" -#include "nrf_log.h" #include -#define PAGE_HEIGHT ((__HEAP_SIZE / 50) - 4) - #define GFX_printf_styled(gfx, fg, bg, font, ...) \ GFX_setTextColor(gfx, fg, bg); \ GFX_setFont(gfx, font); \ @@ -142,13 +138,12 @@ static void DrawTime(Adafruit_GFX *gfx, tm_t *tm, int16_t x, int16_t y, uint16_t Draw7Number(gfx, tm->tm_min, x, y, cS, GFX_BLACK, GFX_WHITE, nD); } -static void DrawBattery(Adafruit_GFX *gfx, int16_t x, int16_t y) +static void DrawBattery(Adafruit_GFX *gfx, int16_t x, int16_t y, float voltage) { - float vol = EPD_ReadVoltage(); - uint8_t level = (uint8_t)(vol * 100 / 4.2); + uint8_t level = (uint8_t)(voltage * 100 / 4.2); GFX_setCursor(gfx, x - 26, y + 9); GFX_setFont(gfx, u8g2_font_wqy9_t_lunar); - GFX_printf(gfx, "%.1fV", vol); + GFX_printf(gfx, "%.1fV", voltage); GFX_fillRect(gfx, x, y, 20, 10, GFX_WHITE); GFX_drawRect(gfx, x, y, 20, 10, GFX_BLACK); GFX_fillRect(gfx, x + 20, y + 4, 2, 2, GFX_BLACK); @@ -162,7 +157,7 @@ static void DrawTemperature(Adafruit_GFX *gfx, int16_t x, int16_t y, int8_t temp GFX_printf(gfx, "%d℃", temp); } -static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, int8_t temp) +static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, gui_data_t *data) { DrawDate(gfx, 40, 36, tm); GFX_setCursor(gfx, 40, 58); @@ -172,8 +167,8 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, int GFX_printf(gfx, "%s%s%s", Lunar_MonthLeapString[Lunar->IsLeap], Lunar_MonthString[Lunar->Month], Lunar_DateString[Lunar->Date]); - DrawBattery(gfx, 330, 25); - DrawTemperature(gfx, 330, 58, temp); + DrawBattery(gfx, 330, 25, data->voltage); + DrawTemperature(gfx, 330, 58, data->temperature); GFX_drawFastHLine(gfx, 30, 68, 330, GFX_BLACK); DrawTime(gfx, tm, 70, 98, 5, 2); @@ -197,24 +192,23 @@ static void DrawClock(Adafruit_GFX *gfx, tm_t *tm, struct Lunar_Date *Lunar, int } } -void DrawGUI(epd_model_t *epd, uint32_t timestamp, display_mode_t mode) +void DrawGUI(gui_data_t *data, buffer_callback draw, display_mode_t mode) { tm_t tm = {0}; struct Lunar_Date Lunar; - transformTime(timestamp, &tm); + transformTime(data->timestamp, &tm); LUNAR_SolarToLunar(&Lunar, tm.tm_year + YEAR0, tm.tm_mon + 1, tm.tm_mday); Adafruit_GFX gfx; - if (epd->bwr) - GFX_begin_3c(&gfx, epd->width, epd->height, PAGE_HEIGHT); + if (data->bwr) + GFX_begin_3c(&gfx, data->width, data->height, PAGE_HEIGHT); else - GFX_begin(&gfx, epd->width, epd->height, PAGE_HEIGHT); + GFX_begin(&gfx, data->width, data->height, PAGE_HEIGHT); GFX_firstPage(&gfx); do { - NRF_LOG_DEBUG("page %d\n", gfx.current_page); GFX_fillScreen(&gfx, GFX_WHITE); switch (mode) { @@ -222,16 +216,12 @@ void DrawGUI(epd_model_t *epd, uint32_t timestamp, display_mode_t mode) DrawCalendar(&gfx, &tm, &Lunar); break; case MODE_CLOCK: - DrawClock(&gfx, &tm, &Lunar, epd->drv->read_temp()); + DrawClock(&gfx, &tm, &Lunar, data); break; default: break; } - } while(GFX_nextPage(&gfx, epd->drv->write_image)); + } while(GFX_nextPage(&gfx, draw)); GFX_end(&gfx); - - NRF_LOG_DEBUG("display start\n"); - epd->drv->refresh(); - NRF_LOG_DEBUG("display end\n"); } diff --git a/GUI/GUI.h b/GUI/GUI.h index 4d16fca..8a51a21 100644 --- a/GUI/GUI.h +++ b/GUI/GUI.h @@ -1,8 +1,11 @@ #ifndef __GUI_H #define __GUI_H -#include -#include "EPD_driver.h" +#include "Adafruit_GFX.h" + +#ifndef PAGE_HEIGHT +#define PAGE_HEIGHT ((__HEAP_SIZE / 50) - 4) +#endif typedef enum { MODE_NONE = 0, @@ -10,6 +13,15 @@ typedef enum { MODE_CLOCK = 2, } display_mode_t; -void DrawGUI(epd_model_t *epd, uint32_t timestamp, display_mode_t mode); +typedef struct { + bool bwr; + uint16_t width; + uint16_t height; + uint32_t timestamp; + int8_t temperature; + float voltage; +} gui_data_t; + +void DrawGUI(gui_data_t *data, buffer_callback draw, display_mode_t mode); #endif diff --git a/Makefile.win32 b/Makefile.win32 new file mode 100644 index 0000000..4303547 --- /dev/null +++ b/Makefile.win32 @@ -0,0 +1,18 @@ +CC = gcc +CFLAGS = -Wall -O2 -IGUI -DPAGE_HEIGHT=600 +LDFLAGS = -lgdi32 -mwindows + +SRCS = GUI/Adafruit_GFX.c GUI/u8g2_font.c GUI/fonts.c GUI/GUI.c GUI/Lunar.c emulator.c +OBJS = $(SRCS:.c=.o) +TARGET = emulator.exe + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJS) $(TARGET) \ No newline at end of file diff --git a/README.md b/README.md index 9c68f40..0ef1b37 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,27 @@ 2. 切换到 `flash_softdevice`,下载蓝牙协议栈,**不要编译直接下载**(只需刷一次) 3. 切换到 `nRF51822_xxAA`,先编译再下载 +### 模拟器 + +本项目提供了一个可在 Windows 下运行界面代码的模拟器,修改了界面代码后无需下载到单片机即可查看效果。 + +仿真效果图: + +![](docs/images/4.jpg) + +> **提示:** 按 `空格` 可切换日历时钟界面,按 `R` 可切换黑白、三色 + +**编译方法:** + +下载并安装 [MSYS2](https://www.msys2.org) 后,打开 `MSYS2 MINGW64` 命令窗口执行: + +```bash +pacman -Syu +pacman -S make mingw-w64-x86_64-gcc +cd <本项目目录> +make -f Makefile.win32 +``` + ## 附录 上位机支持的指令列表(指令和参数全部要使用十六进制): diff --git a/docs/images/4.jpg b/docs/images/4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..17a099e027945d7cc18d711e4d47c6d7bcf64457 GIT binary patch literal 53345 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

I)9SYzIxBpc3_ldD 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

{lMhM-fa)1>vhV>*?ux^*5_vhphohGoU

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 CnP~+8 literal 0 HcmV?d00001 diff --git a/emulator.c b/emulator.c new file mode 100644 index 0000000..b26a33b --- /dev/null +++ b/emulator.c @@ -0,0 +1,262 @@ +// 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 "GUI.h" + +#define BITMAP_WIDTH 400 +#define BITMAP_HEIGHT 300 +#define WINDOW_WIDTH 400 +#define WINDOW_HEIGHT 340 +#define WINDOW_TITLE TEXT("Emurator") + +// Global variables +HINSTANCE g_hInstance; +HWND g_hwnd; +display_mode_t g_display_mode = MODE_CALENDAR; // Default to calendar mode +BOOL g_bwr_mode = TRUE; // Default to BWR mode + +// Convert bitmap data from e-paper format to Windows DIB format +static uint8_t *convertBitmap(uint8_t *bitmap, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + int bytesPerRow = ((w + 31) / 32) * 4; // Round up to nearest 4 bytes + int totalSize = bytesPerRow * h; + + // Allocate memory for converted bitmap + uint8_t *convertedBitmap = (uint8_t*)malloc(totalSize); + if (convertedBitmap == NULL) return NULL; + + memset(convertedBitmap, 0, totalSize); + + int ePaperBytesPerRow = (w + 7) / 8; // E-paper buffer stride + + for (int row = 0; row < h; row++) { + for (int col = 0; col < w; col++) { + // Calculate byte and bit position in e-paper buffer + int bytePos = row * ePaperBytesPerRow + col / 8; + int bitPos = 7 - (col % 8); // MSB first (typical e-paper format) + + // Check if the bit is set in the e-paper buffer + int isSet = (bitmap[bytePos] >> bitPos) & 0x01; + + // Calculate byte and bit position in Windows DIB + int dibBytePos = row * bytesPerRow + col / 8; + int dibBitPos = 7 - (col % 8); // MSB first for DIB too + + // Set the bit in the Windows DIB if it's set in the e-paper buffer + if (isSet) { + convertedBitmap[dibBytePos] |= (1 << dibBitPos); + } + } + } + + return convertedBitmap; +} + +// Implementation of the buffer_callback function +void DrawBitmap(uint8_t *black, uint8_t *color, uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + HDC hdc; + RECT clientRect; + int scale = 1; + + // Get the device context for immediate drawing + hdc = GetDC(g_hwnd); + if (!hdc) return; + + // 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; + + // Create DIB for visible pixels + 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.biPlanes = 1; + bmi.bmiHeader.biBitCount = 1; + bmi.bmiHeader.biCompression = BI_RGB; + + uint8_t *convertedBitmap = convertBitmap(black, x, y, w, h); + if (convertedBitmap == NULL) { + ReleaseDC(g_hwnd, hdc); + return; + } + + // Set colors for black and white display + bmi.bmiColors[0].rgbBlue = 0; + bmi.bmiColors[0].rgbGreen = 0; + bmi.bmiColors[0].rgbRed = 0; + bmi.bmiColors[0].rgbReserved = 0; + + bmi.bmiColors[1].rgbBlue = 255; + bmi.bmiColors[1].rgbGreen = 255; + bmi.bmiColors[1].rgbRed = 255; + bmi.bmiColors[1].rgbReserved = 0; + + // Draw the black layer + StretchDIBits(hdc, + drawX + x * scale, drawY + y * scale, // Destination position + w * scale, h * scale, // Destination size + 0, 0, // Source position + w, h, // Source size + convertedBitmap, // Converted bitmap bits + &bmi, // Bitmap info + DIB_RGB_COLORS, // Usage + SRCCOPY); // Raster operation code + free(convertedBitmap); + + // Handle color layer if present (red in BWR displays) + if (color) { + // Allocate memory for converted color bitmap + uint8_t *convertedColor = convertBitmap(color, x, y, w, h); + if (convertedColor) { + // Set colors for red overlay + bmi.bmiColors[0].rgbBlue = 255; + bmi.bmiColors[0].rgbGreen = 255; + bmi.bmiColors[0].rgbRed = 0; + bmi.bmiColors[0].rgbReserved = 0; + + bmi.bmiColors[1].rgbBlue = 0; + bmi.bmiColors[1].rgbGreen = 0; + bmi.bmiColors[1].rgbRed = 0; + bmi.bmiColors[1].rgbReserved = 0; + + // Draw red overlay + StretchDIBits(hdc, + drawX + x * scale, drawY + y * scale, // Destination position + w * scale, h * scale, // Destination size + 0, 0, // Source position + w, h, // Source size + convertedColor, // Converted bitmap bits + &bmi, // Bitmap info + DIB_RGB_COLORS, // Usage + SRCINVERT); // Use XOR operation to blend + + free(convertedColor); + } + } + + // Release the device context + ReleaseDC(g_hwnd, hdc); +} + +// Window procedure +LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_CREATE: + // Set a timer to update the display periodically (every second) + SetTimer(hwnd, 1, 1000, NULL); + return 0; + + case WM_TIMER: + // Force a redraw of the window without erasing the background + InvalidateRect(hwnd, NULL, FALSE); + return 0; + + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + // Get client rect for calculations + RECT clientRect; + GetClientRect(hwnd, &clientRect); + + // Clear the entire client area with a solid color + HBRUSH bgBrush = CreateSolidBrush(RGB(240, 240, 240)); + FillRect(hdc, &clientRect, bgBrush); + DeleteObject(bgBrush); + + // Get current timestamp + gui_data_t data = { + .bwr = g_bwr_mode, + .width = BITMAP_WIDTH, + .height = BITMAP_HEIGHT, + .timestamp = time(NULL) + 8*3600, + .temperature = 25, + .voltage = 3.2f, + }; + + // Call DrawGUI to render the interface, passing the BWR mode + DrawGUI(&data, DrawBitmap, g_display_mode); + + EndPaint(hwnd, &ps); + return 0; + } + + case WM_KEYDOWN: + // Toggle display mode with spacebar + if (wParam == VK_SPACE) { + if (g_display_mode == MODE_CLOCK) + g_display_mode = MODE_CALENDAR; + else + g_display_mode = MODE_CLOCK; + + InvalidateRect(hwnd, NULL, TRUE); + } + // Toggle BWR mode with R key + else if (wParam == 'R') { + g_bwr_mode = !g_bwr_mode; + InvalidateRect(hwnd, NULL, TRUE); + } + return 0; + + case WM_DESTROY: + KillTimer(hwnd, 1); + PostQuitMessage(0); + return 0; + + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } +} + +// Main entry point +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + g_hInstance = hInstance; + + // Register window class + WNDCLASSA wc = {0}; // Using WNDCLASSA for ANSI version + 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.lpszClassName = "BitmapDemo"; // No L prefix - using ANSI strings + + if (!RegisterClassA(&wc)) { + MessageBoxA(NULL, "Window Registration Failed!", "Error", MB_ICONEXCLAMATION | MB_OK); + return 0; + } + + // Create the window - explicit use of CreateWindowA for ANSI version + g_hwnd = CreateWindowA( + "BitmapDemo", + "Emurator (Press Space/R Key)", // Using simple title + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + WINDOW_WIDTH, WINDOW_HEIGHT, + NULL, NULL, hInstance, NULL + ); + + if (!g_hwnd) { + MessageBoxA(NULL, "Window Creation Failed!", "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