#include "../2025_include_user/OledMenuDriver.h" #define OLED_I2C_ADDR (0x3C) // 7-bit地址,不需要 <<1 #define SYSTEM_CORE_CLOCK_HZ 80000000U u8g2_t MenuDriver::u8g2 = {}; uint8_t u8x8_gpio_and_delay_mspm0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch (msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: delay_cycles(32000); //1ms break; case U8X8_MSG_DELAY_MILLI: for (uint8_t i = 0; i < arg_int; i++) { delay_cycles(32000); } break; case U8X8_MSG_GPIO_DC: break; case U8X8_MSG_GPIO_RESET: /** if (arg_int) { DL_GPIO_setPins(GPIO_OLED_PORT, GPIO_OLED_RST_OLED_PIN); } else { DL_GPIO_clearPins(GPIO_OLED_PORT, GPIO_OLED_RST_OLED_PIN); }**/ break; } return 1; } uint8_t u8x8_byte_mspm0_hw_i2c(u8x8_t *u8g2, uint8_t msg, uint8_t arg_int, void *arg_ptr) { /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */ /* add extra byte for the i2c address */ static uint8_t buffer[34]; static volatile uint8_t buf_idx, g_u8TxCount; uint8_t *data; switch (msg) { case U8X8_MSG_BYTE_SEND: data = (uint8_t *) arg_ptr; while (arg_int > 0) { buffer[buf_idx++] = *data; data++; arg_int--; } break; case U8X8_MSG_BYTE_INIT: /* add your custom code to init i2c subsystem */ break; case U8X8_MSG_BYTE_SET_DC: /* ignored for i2c */ break; case U8X8_MSG_BYTE_START_TRANSFER: buf_idx = 0; break; case U8X8_MSG_BYTE_END_TRANSFER: /* * Fill FIFO with data. */ g_u8TxCount = DL_I2C_fillControllerTXFIFO(I2C_0_INST, &buffer[0], buf_idx); /* Wait for I2C to be Idle */ while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)); /* Send the packet to the controller. * This function will send Start + Stop automatically. */ DL_I2C_startControllerTransfer(I2C_0_INST, OLED_I2C_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, buf_idx); while (g_u8TxCount < buf_idx) { while (DL_I2C_isControllerTXFIFOFull(I2C_0_INST) == true); DL_I2C_transmitControllerData(I2C_0_INST, buffer[g_u8TxCount]); g_u8TxCount++; } /* Poll until the Controller writes all bytes */ while (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS); /* Trap if there was an error */ if (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_ERROR) { while (1); } /* Wait for I2C to be Idle */ while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)); DL_I2C_flushControllerTXFIFO(I2C_0_INST); break; default: return 0; } return 1; } void MenuDriver::oled_init() { u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_mspm0_hw_i2c, u8x8_gpio_and_delay_mspm0); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); u8g2_ClearBuffer(&u8g2); } void MenuDriver::ssd1306_transmit_cmd(uint8_t cmd) { uint8_t temp[2] = {0x00, cmd}; DL_I2C_fillControllerTXFIFO(I2C_0_INST, temp, 2); while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)); DL_I2C_startControllerTransfer(I2C_0_INST, OLED_I2C_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, 2); while (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS); while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)); DL_I2C_flushControllerTXFIFO(I2C_0_INST); } void MenuDriver::ssd1306_transmit_data(uint8_t data, const uint8_t mode) { if (!mode) data = ~data; uint8_t temp[2] = {0x40, data}; DL_I2C_fillControllerTXFIFO(I2C_0_INST, temp, 2); while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)); DL_I2C_startControllerTransfer(I2C_0_INST, OLED_I2C_ADDR, DL_I2C_CONTROLLER_DIRECTION_TX, 2); while (DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS); while (!(DL_I2C_getControllerStatus(I2C_0_INST) & DL_I2C_CONTROLLER_STATUS_IDLE)); DL_I2C_flushControllerTXFIFO(I2C_0_INST); } void MenuDriver::ssd1306_set_cursor(unsigned char _x, unsigned char _y) { ssd1306_transmit_cmd(0xB0 | _y); ssd1306_transmit_cmd(0x10 | ((_x & 0xF0) >> 4)); ssd1306_transmit_cmd(0x00 | (_x & 0x0F)); } void MenuDriver::ssd1306_fill(unsigned char _data) { for (uint8_t page = 0; page < 8; ++page) { ssd1306_set_cursor(0, page); for (uint8_t col = 0; col < 128; ++col) { ssd1306_transmit_data(_data, 1); } } } void MenuDriver::screenOn() { ssd1306_transmit_cmd(0X8D); ssd1306_transmit_cmd(0X14); ssd1306_transmit_cmd(0XAF); } void MenuDriver::screenOff() { ssd1306_transmit_cmd(0X8D); ssd1306_transmit_cmd(0X10); ssd1306_transmit_cmd(0XAE); } void *MenuDriver::getCanvasBuffer() { return u8g2_GetBufferPtr(&u8g2); } uint8_t MenuDriver::getBufferTileHeight() { return u8g2_GetBufferTileHeight(&u8g2); } uint8_t MenuDriver::getBufferTileWidth() { return u8g2_GetBufferTileWidth(&u8g2); } void MenuDriver::canvasUpdate() { u8g2_SendBuffer(&u8g2); } void MenuDriver::canvasClear() { u8g2_ClearBuffer(&u8g2); } void MenuDriver::setFont(const uint8_t *_font) { u8g2_SetFontMode(&u8g2, 1); u8g2_SetFontDirection(&u8g2, 0); u8g2_SetFont(&u8g2, _font); } void MenuDriver::setFont(const uint8_t *_font, uint8_t _font_mode, uint8_t _font_direction) { u8g2_SetFontMode(&u8g2, _font_mode); u8g2_SetFontDirection(&u8g2, _font_direction); u8g2_SetFont(&u8g2, _font); } uint8_t MenuDriver::getFontWidth(const char *_text) { return u8g2_GetUTF8Width(&u8g2, _text); } uint8_t MenuDriver::getFontHeight() { return u8g2_GetMaxCharHeight(&u8g2); } void MenuDriver::setDrawType(uint8_t _type) { u8g2_SetDrawColor(&u8g2, _type); } void MenuDriver::drawPixel(float _x, float _y) { u8g2_DrawPixel(&u8g2, (int16_t) round(_x), (int16_t) round(_y)); } void MenuDriver::draw(float _x, float _y, const char *_text) { setFont(u8g2_font_wqy14_t_chinese3); u8g2_DrawUTF8(&u8g2, (int16_t) round(_x), (int16_t) round(_y), _text); } void MenuDriver::draw(float _x, float _y, const char *_text, uint8_t _font_mode, uint8_t _font_direction) { setFont(u8g2_font_wqy14_t_chinese3, _font_mode, _font_direction); u8g2_DrawUTF8(&u8g2, (int16_t) round(_x), (int16_t) round(_y), _text); } void MenuDriver::draw(float _x, float _y, const char *_text, const uint8_t *_font, uint8_t _font_mode, uint8_t _font_direction) { setFont(_font, _font_mode, _font_direction); u8g2_DrawUTF8(&u8g2, (int16_t) round(_x), (int16_t) round(_y), _text); } void MenuDriver::drawEnglish(float _x, float _y, const char *_text) { setFont(u8g2_font_wqy14_t_chinese3); u8g2_DrawStr(&u8g2, (int16_t) round(_x), (int16_t) round(_y), _text); } void MenuDriver::drawChinese(float _x, float _y, const char *_text) { setFont(u8g2_font_wqy14_t_chinese3); u8g2_DrawUTF8(&u8g2, (int16_t) round(_x), (int16_t) round(_y), _text); } void MenuDriver::drawVDottedLine(float _x, float _y, float _h) { for (unsigned char i = 0; i < (unsigned char) round(_h); i++) { if (i % 8 == 0 || (i - 1) % 8 == 0 || (i - 2) % 8 == 0) continue; u8g2_DrawPixel(&u8g2, (int16_t) round(_x), (int16_t) round(_y) + i); } } void MenuDriver::drawHDottedLine(float _x, float _y, float _l) { for (unsigned char i = 0; i < _l; i++) { if (i % 8 == 0 || (i - 1) % 8 == 0 || (i - 2) % 8 == 0) continue; u8g2_DrawPixel(&u8g2, (int16_t) round(_x) + i, (int16_t) round(_y)); } } void MenuDriver::drawVLine(float _x, float _y, float _h) { u8g2_DrawVLine(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_h)); } void MenuDriver::drawHLine(float _x, float _y, float _l) { u8g2_DrawHLine(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_l)); } void MenuDriver::drawBMP(float _x, float _y, float _w, float _h, const uint8_t *_bitMap) { u8g2_DrawXBMP(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_w), (int16_t) round(_h), _bitMap); } void MenuDriver::drawBox(float _x, float _y, float _w, float _h) { u8g2_DrawBox(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_w), (int16_t) round(_h)); } void MenuDriver::drawRBox(float _x, float _y, float _w, float _h, float _r) { u8g2_DrawRBox(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_w), (int16_t) round(_h), (int16_t) round(_r)); } void MenuDriver::drawFrame(float _x, float _y, float _w, float _h) { u8g2_DrawFrame(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_w), (int16_t) round(_h)); } void MenuDriver::drawRFrame(float _x, float _y, float _w, float _h, float _r) { u8g2_DrawRFrame(&u8g2, (int16_t) round(_x), (int16_t) round(_y), (int16_t) round(_w), (int16_t) round(_h), (int16_t) round(_r)); } void MenuDriver::drawCheckMark(float x, float y, float w, float h) { float x0 = x + w * 0.1f; float y0 = y + h * 0.5f; float x1 = x + w * 0.4f; float y1 = y + h * 0.8f; float x2 = x + w * 0.9f; float y2 = y + h * 0.2f; u8g2_DrawLine(&u8g2, (int16_t) round(x0), (int16_t) round(y0), (int16_t) round(x1), (int16_t) round(y1)); u8g2_DrawLine(&u8g2, (int16_t) round(x1), (int16_t) round(y1), (int16_t) round(x2), (int16_t) round(y2)); }