niobe/applications/app/TW402_APP_oled_u8g2/src/oled_u8g2.c

323 lines
8.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2021 Talkweb Co.,ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_i2c.h"
#include "u8g2.h"
#include "u8x8.h"
#include "oled_u8g2.h"
#include "boot_animation.h"
volatile osSemaphoreId_t g_gpioIsrSemId = NULL;
volatile char g_startBootAnimationFlag = 0;
static u8g2_t u8g2;
I2C_SEND_STATES g_i2cSendState = STATE_SEND_IDLE;
#define MAX_DATAS 1200
#define EVERY_DATA_SEND 16
unsigned char g_send_data[2] = {0};
unsigned char g_send_datas[MAX_DATAS] = {0};
//OLED通信端口
#define WIFI_IOT_I2C_IDX_0 0
#define OLED_I2C_BAUDRATE (100 * 1000) // 400k 频率
#define SSD1306_I2C_ADDR (0x3C << 1)
#define SSD1306_CTRL_CMD 0x00
#define SSD1306_CTRL_DATA 0x40
#define FEATURE_ISQ_CONTROLL 1
//信号管脚
#define WIFI_IOT_IO_NAME_GPIO_13 13
#define WIFI_IOT_IO_NAME_GPIO_14 14
static uint32_t HALI2cWriteDatas(unsigned int id, uint16_t device_addr, uint32_t send_len)
{
unsigned int status;
status = IoTI2cWrite(id, device_addr, g_send_datas, send_len);
if (status != 0)
{
printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
return status;
}
return 0;
}
/**
* SSD1306写data数据
*/
static void WriteIICDatas(unsigned char *IIC_Datas, uint32_t length)
{
memset_s(g_send_datas, MAX_DATAS, 0, MAX_DATAS);
g_send_datas[0] = SSD1306_CTRL_DATA;
memcpy_s(g_send_datas + 1, MAX_DATAS, IIC_Datas, length);
HALI2cWriteDatas(WIFI_IOT_I2C_IDX_0, SSD1306_I2C_ADDR, length + 1);
}
/**
* SSD1306写CMD数据
*/
static void WriteIICCmds(unsigned char *IIC_Datas, uint32_t length)
{
memset_s(g_send_datas, MAX_DATAS, 0, MAX_DATAS);
g_send_datas[0] = SSD1306_CTRL_CMD;
memcpy_s(g_send_datas + 1, MAX_DATAS, IIC_Datas, length);
HALI2cWriteDatas(WIFI_IOT_I2C_IDX_0, SSD1306_I2C_ADDR, length + 1);
}
static void HalDelayMs(uint32_t ms)
{
uint32_t msPerTick = 1000 / osKernelGetTickFreq(); // 10ms
if (ms >= msPerTick)
{
osDelay((ms / msPerTick));
}
uint32_t restMs = ms % msPerTick;
if (restMs > 0)
{
usleep(restMs * 1000);
}
}
static void HalI2cInit()
{
IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_13);
IoTGpioInit(WIFI_IOT_IO_NAME_GPIO_14);
IotIoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
IotIoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
IoTI2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE);
}
uint8_t U8g2Hi3861I2cByteCb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t *data;
uint8_t index;
switch (msg)
{
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
if (g_i2cSendState == STATE_SEND_START && arg_int == 1)
{
if (*data == 0x00)
{
g_i2cSendState = STATE_SEND_CMD;
break;
}
else if (*data == 0x40)
{
g_i2cSendState = STATE_SEND_DATA;
break;
}
else
{
// do nonthing
}
}
if (g_i2cSendState == STATE_SEND_CMD)
{
WriteIICCmds(data, arg_int);
}
else if (g_i2cSendState == STATE_SEND_DATA)
{
WriteIICDatas(data, arg_int);
}
else
{
// do nothing
}
break;
case U8X8_MSG_BYTE_INIT:
HalI2cInit();
break;
case U8X8_MSG_BYTE_START_TRANSFER:
if (g_i2cSendState == STATE_SEND_IDLE)
{
g_i2cSendState = STATE_SEND_START;
}
else
{
g_i2cSendState = STATE_SEND_IDLE;
}
break;
case U8X8_MSG_BYTE_END_TRANSFER: // send all at once
if (g_i2cSendState == STATE_SEND_CMD || g_i2cSendState == STATE_SEND_DATA)
{
g_i2cSendState = STATE_SEND_IDLE;
}
break;
default:
return 0;
}
return 1;
}
uint8_t U8g2Hi3861GpioAndDelayCb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
switch (msg)
{
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
__asm__ volatile("nop");
break;
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
__asm__ volatile("nop");
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
usleep(10);
break;
case U8X8_MSG_DELAY_MILLI:
HalDelayMs(arg_int);
break;
case U8X8_MSG_GPIO_AND_DELAY_INIT:
break;
case U8X8_MSG_GPIO_RESET:
break;
case U8X8_MSG_GPIO_I2C_DATA:
break;
case U8X8_MSG_GPIO_I2C_CLOCK:
break;
}
return 0;
}
static unsigned int g_lastTickCount = 0;
static void GpioSsdIsrFunc(char *arg)
{
(void)arg;
//消除按键抖动
unsigned int tickCount = osKernelGetTickCount();
unsigned int count = tickCount - g_lastTickCount;
g_lastTickCount = tickCount;
if (count > 50)
{
g_startBootAnimationFlag ^= 1;
osSemaphoreRelease(g_gpioIsrSemId);
}
return;
}
/**
* 初始化开发板上的按键GPIO中断
*/
static void InitOledKeyGpioIsr(void)
{
g_gpioIsrSemId = osSemaphoreNew(32, 0, NULL);
IoTGpioInit(IOT_GPIO_IO_GPIO_5);
IotIoSetFunc(IOT_GPIO_IO_GPIO_5, HI_IO_FUNC_GPIO_5_GPIO);
IotIoSetPull(IOT_GPIO_IO_GPIO_5, IOT_IO_PULL_UP);
uint32_t ret = 0;
ret = IoTGpioSetDir(IOT_GPIO_IO_GPIO_5, IOT_GPIO_DIR_IN);
if (ret != 0)
{
printf("===== ERROR ======gpio -> hi_gpio_set_dir1 ret:%d\r\n", ret);
return;
}
ret = IoTGpioRegisterIsrFunc(IOT_GPIO_IO_GPIO_5, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_RISE_LEVEL_HIGH, GpioSsdIsrFunc, NULL);
return;
}
/**
* 绘制HarmonyOS开机动画
*/
static void DrawHarmonyOSAnimation(void)
{
for (int i = 0; i < 58; i++)
{
u8g2_FirstPage(&u8g2);
do
{
u8g2_DrawXBMP(&u8g2, 0, 0, 128, 64, openHarmony_All[i]);
} while (u8g2_NextPage(&u8g2));
}
}
/**
* 绘制Talkweb LOGO未来已来,远方不远
*/
static void DrawTalkwebLogo(void)
{
u8g2_FirstPage(&u8g2);
do
{
u8g2_DrawXBMP(&u8g2, 0, 0, 128, 64, talkweb_end);
} while (u8g2_NextPage(&u8g2));
}
static void OledU8g2Task(void)
{
//初始化OLED开发板上的按键中断事件
InitOledKeyGpioIsr();
//U8G2_R0屏幕旋转方向横屏不旋转。
u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, U8g2Hi3861I2cByteCb, U8g2Hi3861GpioAndDelayCb);
//初始OLED显示器将向OLED显示器发送init消息
//此函数会触发两种操作一种是OLED硬件初始一种是OLED显示屏初始清屏。
u8g2_InitDisplay(&u8g2);
//开启省电模式
u8g2_SetPowerSave(&u8g2, 0);
while (1)
{
DrawTalkwebLogo();
osSemaphoreAcquire(g_gpioIsrSemId, osWaitForever);
while (g_startBootAnimationFlag)
{
DrawHarmonyOSAnimation();
osDelay(300U);
DrawTalkwebLogo();
osDelay(300U);
}
}
}
bool StartBootAnimation()
{
osThreadAttr_t attr;
attr.name = "OledU8g2Task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 1024 * 10;
attr.priority = osPriorityNormal;
if (osThreadNew((osThreadFunc_t)OledU8g2Task, NULL, &attr) == NULL)
{
printf("[Talkweb Niobe] Falied to create OledU8g2Task!\n");
return false;
}
return true;
}