【开源】AIoT LCM平台开发自已的OS内核《一》
本帖最后由 神秘の宅叔 于 2022-2-25 15:54 编辑用户不仅能使用AIoT LCM平台的串口指令集与AIoT LCM平台交互,实现界面的显示以及响应,还可以在AIoT LCM平台上开发自已的OS内核程序,直接在OS内核程序中获取输入事件,控制界面显示。视频演示:
还要请提醒大家的是,示例工程对应的是AIoT LCM平台,采用主频353.8944MHZ主频,显示分辨率为1024X600的设备,其它分辨率或平台如果不修改是无法正常工作的。
由于作者本人开发的这套源码的时间比较早,建议只参考C51的源码,其他的文件都不要直接下载到屏,可能会发生不兼容的现象。
https://v.qq.com/x/page/p0970m0rc5z.html
http://cache.tv.qq.com/qqplayerout.swf?vid=p0970m0rc5z
下面分步详细介绍实现的步骤:
一、安装uVision,推荐版本为V5.25.3.0
二、安装迪文支持库,见附件驱动程序及支持库;
三、创建资源文件,每个需要烧录的文件统一编号,文件名前缀为其编号数值,每个编号占用1MBytes的FLASH区域
1、字库文件,详见《AIoT LCM_TA指令集V10》
2、背景图片,使用AllToolForAIOT 转换成ICM文件,(一般编号为32);
3、图标文件,使用AllToolForAIOT 转换成ICM文件,每个ICM文件中可以包含多个图标,给每个ICM文件编号;
4、音乐文件,使用AllToolForAIOT转换成WAM文件,给每个WAM文件编号;
5、UIF文件,使用迪文提供的"UIF生成工具"制作,一般编号为13;
6、T5LCFGXX.CFG配置文件,详见《AIoT LCM_TA指令集V10》中对配置文件的定义;
四、创建自已的工程
1、使用Keil创建新的工程
2、把迪文提供的SFR文件《T5LOS8051.h》,《T5L_OS_8051.INC》放在编译器能够找得到的位置,也可以直接拷贝过来放在工程目录下;
3、把参考代码中的文件拷贝到工程目录下,并添加到工程中;
STARTUP_M5.A51,程序引导汇编入口;
sys.c,sys.h:CPU及设备和定时器的初始化,以及相应访问接口
uart.c,uart.h:串口2的接收与发送,串口指令集的帧通讯实现;
cmd.c,cmd.h:串口2指令集解析及执行;
paint.c,paint.h:对AIoT LCM平台GUI系统的访问与控制,实现界面绘制;
4、创建自已的主控程序,参照main.c以及player.c;
五、程序中调用资源文件实现界面交互,与界面的交互过程实际上就是与用户(操作者)的交互过程,用户通过触摸或者按键控制设备,设备上的显示器显示图形化的界面给用户,因此程序逻辑可以按以下处理:
1、初始化界面,通过指定背景图显示,局部通过程序调用资源文件绘制形成;参考代码中已经通过UIF文件指定了32号文件为背景图,同时player.c中initPlayer()函数针对音乐播放界面和视频播放界面进行了局部按钮显示;
2、用户输入检测:参考player.c中的processInput函数,此函数在cmd.c的checkAndSendTP2Uart函数中被调用,而checkAndSendTP2Uart被主函数定时调用,查询用户是否有操作动作。
3、用户输入的响应:根据不同的应用,处理输入事件,进行特定的响应,参考代码实现了一个媒体播放器的基本功能,用户操作播放、暂停键,可以上一首,下一首,调节音量,详见processInput函数中对各输入事件的响应处理;
4、定时响应或内部流程的处理:这些流程不是由用户触发的,而是程序自主监控产生。为了实现播放进度条动态变化,必须在主控流程中增加播放进度查询,从而更新播放进度条,详见player.c中processProgDisplay函数的处理。
5、特定功能的实现,对于设备控制,声音视频播放等,他们一般通过控制其它系统完成指定功能,如player.c中播放音视频的相关函数,playAudio,playVideo;
六、参考代码分析
1、player.c
/***************************************************************************************
版权所有 (C), 2020, 北京迪文科技有限公司
***************************************************************************************
文 件 名 : player.c
版 本 号 :
作 者 :
生成日期 : 2020年4月30日
功能描述 : 音乐播放器的逻辑流程实现,包括输入与用户交互流程,界面显示流程;
修改历史 :
1.日 期 :
作 者 :
修改内容 :
****************************************************************************************/
#include <stdio.h>
#include<string.h>
#include "cmd.h"
#include "paint.h"
#include "player.h"
#include "uart.h"
//显示布局;
//进度条左上角位置;
#define X_AUDIO_POS_PROGRESS 262
#define Y_AUDIO_POS_PROGRESS 304
#define X_VIDEO_POS_PROGRESS 106
#define Y_VIDEO_POS_PROGRESS 495
//音量进度条左上角位置和尺寸;
#define X_AUDIO_POS_VOL 943
#define Y_AUDIO_POS_VOL 111
#define X_VIDEO_POS_VOL 943
#define Y_VIDEO_POS_VOL 111
#define VOLUME_PIC_WIDTH 59
#define VOLUME_PIC_HEIGHT 285
//音乐播放界面,文字显示位置;
#define X_POS_PTEXT 436
#define Y_POS_PTEXT 420
//音乐播放界面,按钮显示位置;
#define X_AUDIO_BUTTON_PREV 399
#define Y_AUDIO_BUTTON_PREV 313
#define X_AUDIO_BUTTON_PLAY 460
#define Y_AUDIO_BUTTON_PLAY 296
#define X_AUDIO_BUTTON_NEXT 594
#define X_BUTTON_TO_VIDEO 30
#define Y_BUTTON_TO_VIDEO 516
//视频播放界面,按钮显示位置;
#define X_VIDEO_BUTTON_PREV 325
#define Y_VIDEO_BUTTON_PREV 510
#define X_VIDEO_BUTTON_PLAY 449
#define Y_VIDEO_BUTTON_PLAY 507
#define X_VIDEO_BUTTON_NEXT 615
#define X_BUTTON_TO_AUDIO 862
#define Y_BUTTON_TO_AUDIO 524
//按钮文件中各按钮的序号定义;
#define BUTTON_ID_VIDEO_PLAY 0
#define BUTTON_ID_VIDEO_PAUSE 2
#define BUTTON_ID_AUDIO_PLAY1
#define BUTTON_ID_AUDIO_PAUSE 3
#define BUTTON_ID_VIDEO_PREV 6
#define BUTTON_ID_VIDEO_PREVI 7
#define BUTTON_ID_VIDEO_NEXT 4
#define BUTTON_ID_VIDEO_NEXTI 5
#define BUTTON_ID_AUDIO_PREV 14
#define BUTTON_ID_AUDIO_PREVI 15
#define BUTTON_ID_AUDIO_NEXT 12
#define BUTTON_ID_AUDIO_NEXTI 13
#define BUTTON_ID_TO_AUDIO 10
#define BUTTON_ID_TO_AUDIOI 11
#define BUTTON_ID_TO_VIDEO 8
#define BUTTON_ID_TO_VIDEOI 9
//背景图片文件中,各背景的页面的定义;
#define PAGE_ID_AUDIO 0
#define PAGE_ID_VIDEO 1
//各文件ID的定义;
#define FILE_ID_BUTTON 36
#define FILE_ID_AUDIO_VOLUME 37
#define FILE_ID_VIDEO_VOLUME 38
#define FILE_ID_VIDEO_PROGRESS 60
#define FILE_ID_AUDIO_PROGRESS 64
//音量控制;
static int audioVolume;
//播放控制;
static u16 playPosition;
static u16 playTotalDuration;
static int oldProgressFrame;//用于记忆上一次刷新的位置,避免频繁调用。
static u8playStation;//0x00:stop,0x01:playing;0x02:pause;
static u8pageID;//当前显示的页面;
static intcurrPlayIndex;//当前播放的文件索引,包括音乐和视频;
//音乐和视频表,便于通过索引统一访问。
static const unsigned char code m_audioID = { 0x50,0x6C,0x84 };
static const unsigned char code m_videoID = { 186,155, 172};
static const unsigned char code m_videoAudioID = { 181,152,168 };
~
extern u8 xdata send_buffer;
/*****************************************************************************************
初始化音乐播放器相关参数,初始化界面;
******************************************************************************************/
void initPlayer(void)
{
audioVolume = 8;
switchToAudio();
}
/*****************************************************************************************
切换到音乐播放页面,显示默认画面,按钮及进度条的初始状态。
******************************************************************************************/
static void switchToAudio(void)
{
stopVideo();
playPosition = 0x0000;
playTotalDuration = 0xFFFF;
playStation = 0x00;
switchPage(PAGE_ID_AUDIO);
pageID = PAGE_ID_AUDIO;
oldProgressFrame = -1;
currPlayIndex = 0;
drawPicture(X_AUDIO_BUTTON_PREV,Y_AUDIO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PREV);
drawPicture(X_AUDIO_BUTTON_PLAY,Y_AUDIO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PLAY);
drawPicture(X_AUDIO_BUTTON_NEXT,Y_AUDIO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_AUDIO_NEXT);
drawPicture(X_AUDIO_POS_PROGRESS,Y_AUDIO_POS_PROGRESS,FILE_ID_AUDIO_PROGRESS,0);
drawPicture(X_AUDIO_POS_VOL,Y_AUDIO_POS_VOL,FILE_ID_AUDIO_VOLUME,audioVolume);
drawPicture(X_BUTTON_TO_VIDEO,Y_BUTTON_TO_VIDEO,FILE_ID_BUTTON,BUTTON_ID_TO_VIDEO);
}
/*****************************************************************************************
切换到视频播放页面,显示默认画面,按钮及进度条的初始状态。
******************************************************************************************/
static void SwitchToVideo(void)
{
stopAudio();
playPosition = 0x0000;
playTotalDuration = 0xFFFF;
playStation = 0x00;
switchPage(PAGE_ID_VIDEO);
pageID = PAGE_ID_VIDEO;
currPlayIndex = 0;
oldProgressFrame = -1;
drawPicture(X_VIDEO_BUTTON_PREV,Y_VIDEO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PREV);
drawPicture(X_VIDEO_BUTTON_PLAY,Y_VIDEO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PLAY);
drawPicture(X_VIDEO_BUTTON_NEXT,Y_VIDEO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_VIDEO_NEXT);
setDrawMode(0x01);//贴图时背景色一起绘上;
drawPicture(X_VIDEO_POS_PROGRESS,Y_VIDEO_POS_PROGRESS,FILE_ID_VIDEO_PROGRESS,0);
setDrawMode(0x00);//返回默认模式,不贴背景色;
drawPicture(X_VIDEO_POS_VOL,Y_VIDEO_POS_VOL,FILE_ID_VIDEO_VOLUME,audioVolume);
drawPicture(X_BUTTON_TO_AUDIO,Y_BUTTON_TO_AUDIO,FILE_ID_BUTTON,BUTTON_ID_TO_AUDIO);
}
/*****************************************************************************************
响应用户对触摸屏的操作,通过触控文件,已经由GUI核转换成了按键值,根据弹起的按键值,进行各种
处理。
tp:触摸屏的命令类型与数据;
******************************************************************************************/
void processInput(u8* tp)
{
if(tp == 0x78){//弹起
switch(tp){
case 1://切换到视频播放页面;
SwitchToVideo();
break;
case 2://音量增加
case 17:
if(audioVolume < 20){
audioVolume++;
adjustVolume();
}
break;
case 3://音量减小;
case 18:
if(audioVolume > 0){
audioVolume--;
adjustVolume();
}
break;
case 4://前一首音乐;
onAudioPrev();
break;
case 5://后一首音乐;
onAudioNext();
break;
case 6://音乐播放、暂停;
onAudioPlayPause();
break;
case 7://切换到音乐播放界面;
switchToAudio();
break;
case 8://上一部电影;
onVideoPrev();
break;
case 9://下一部电影;
onVideoNext();
break;
case 16://视频播放,暂停;
onVideoPlayPause();
break;
default:
break;
}
}
}
/*****************************************************************************************
音乐播放控制,通知GUI核播放哪个文件,以及从什么地方开始播放,使用当前音量和播放类型;
start:播放的起始时间点;
fileid:将播放的文件ID;
******************************************************************************************/
static void playAudio(u16 starts,u16 fileid)
{
unsigned short av = 2048/20 * audioVolume;
memset(send_buffer,0,16);
send_buffer = 0x5A;
send_buffer = 0x01;
send_buffer = (starts >> 8) & 0xFF;
send_buffer = starts & 0xFF;
send_buffer = (fileid>> 8 )& 0xFF;
send_buffer = (fileid) & 0xFF;
send_buffer = (unsigned char)((av >> 8)& 0xFF);
send_buffer = (unsigned char)(av & 0xFF);
write_dgus_vp(0x00C0,send_buffer,6);
}
/*****************************************************************************************
停止音乐播放界面的播放,一般用于音视频间的切换;
******************************************************************************************/
static void stopAudio(void)
{
if(pageID != PAGE_ID_AUDIO)
return;
if(playStation == 0x01 ){
send_buffer = 0x5A;
send_buffer = 0x02;
write_dgus_vp(0x00C0,send_buffer,1);
playStation = 0x00;
}
}
/*****************************************************************************************
停止视频播放界面的播放,一般用于音视频间的切换;
******************************************************************************************/
static void stopVideo(void)
{
if(pageID != PAGE_ID_VIDEO)
return;
if(playStation == 0x01 ){
send_buffer = 0x5A;
send_buffer = 0x02;
write_dgus_vp(0x00C8,send_buffer,1);
send_buffer = 0x5A;
send_buffer = 0x02;
write_dgus_vp(0x00C0,send_buffer,1);
playStation = 0x00;
}
}
/*****************************************************************************************
响应音乐播放及暂停按键,控制GUI进行播放和暂停,同时更新按钮的显示;
******************************************************************************************/
static void onAudioPlayPause(void)
{
if(playStation != 0x00 ){
memset(send_buffer,0,16);
send_buffer = 0x5A;
send_buffer = 0x02;
write_dgus_vp(0x00C0,send_buffer,1);
if(playStation == 0x01){
playStation = 0x02;
drawPicture(X_AUDIO_BUTTON_PLAY,Y_AUDIO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PLAY);
}
else{
playStation = 0x01;
drawPicture(X_AUDIO_BUTTON_PLAY,Y_AUDIO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PAUSE);
}
}
else{
u16 fileid = m_audioID;
playAudio(0x0000,fileid);
playStation = 0x01;
drawPicture(X_AUDIO_BUTTON_PLAY,Y_AUDIO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PAUSE);
}
}
/*****************************************************************************************
响应视频播放及暂停按键,控制GUI进行播放和暂停,同时更新按钮的显示;
******************************************************************************************/
static void onVideoPlayPause(void)
{
if(playStation != 0x00 ){
memset(send_buffer,0,16);
send_buffer = 0x5A;
send_buffer = 0x02;
write_dgus_vp(0x00C0,send_buffer,1);
send_buffer = 0x5A;
send_buffer = 0x02;
write_dgus_vp(0x00C8,send_buffer,1);
if(playStation == 0x01){
playStation = 0x02;
drawPicture(X_VIDEO_BUTTON_PLAY,Y_VIDEO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PLAY);
}
else{
playStation = 0x01;
drawPicture(X_VIDEO_BUTTON_PLAY,Y_VIDEO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PAUSE);
}
}
else{
u16 fileid = m_videoID;
playVideo(0x0000,fileid);
fileid = m_videoAudioID;
playAudio(0x0000,fileid);
playStation = 0x01;
drawPicture(X_VIDEO_BUTTON_PLAY,Y_VIDEO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PAUSE);
}
}
/*****************************************************************************************
响应音乐播放界面的下一首按键,跳转到下一首,同时更新下一首按钮的显示;
******************************************************************************************/
static void onAudioNext(void)
{
u16 fileid;
if(currPlayIndex >= 2)
return;
currPlayIndex++;
fileid = m_audioID;
playAudio(0x0000,fileid);
playStation = 0x01;
drawPicture(X_AUDIO_BUTTON_PLAY,Y_AUDIO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PAUSE);
if(currPlayIndex == 2){
drawPicture(X_AUDIO_BUTTON_NEXT,Y_AUDIO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_AUDIO_NEXTI);
}
drawPicture(X_AUDIO_BUTTON_PREV,Y_AUDIO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PREV);
}
/*****************************************************************************************
响应音乐播放界面的前一首按键,跳转到前一首,同时更新前一首按钮的显示;
******************************************************************************************/
static void onAudioPrev(void)
{
u16 fileid;
if( currPlayIndex <= 0 )
return;
currPlayIndex--;
fileid = m_audioID;
playAudio(0x0000,fileid);
playStation = 0x01;
drawPicture(X_AUDIO_BUTTON_PLAY,Y_AUDIO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PAUSE);
if(currPlayIndex == 0){
drawPicture(X_AUDIO_BUTTON_PREV,Y_AUDIO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_AUDIO_PREVI);
}
drawPicture(X_AUDIO_BUTTON_NEXT,Y_AUDIO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_AUDIO_NEXT);
}
/*****************************************************************************************
响应视频播放界面的前一首按键,跳转到前一首,同时更新前一首按钮的显示;
******************************************************************************************/
static void onVideoPrev(void)
{
u16 fileid;
if( currPlayIndex <= 0 )
return;
currPlayIndex--;
fileid = m_videoID;
playVideo(0x0000,fileid);
fileid = m_videoAudioID;
playAudio(0x0000,fileid);
playStation = 0x01;
drawPicture(X_VIDEO_BUTTON_PLAY,Y_VIDEO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PAUSE);
if(currPlayIndex == 0){
drawPicture(X_VIDEO_BUTTON_PREV,Y_VIDEO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PREVI);
}
drawPicture(X_VIDEO_BUTTON_NEXT,Y_VIDEO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_VIDEO_NEXT);
}
/*****************************************************************************************
响应视频播放界面的下一首按键,跳转到下一首,同时更新下一首按钮的显示;
******************************************************************************************/
static void onVideoNext(void)
{
u16 fileid;
if(currPlayIndex >= 2)
return;
currPlayIndex++;
fileid = m_videoID;
playVideo(0x0000,fileid);
fileid = m_videoAudioID;
playAudio(0x0000,fileid);
playStation = 0x01;
drawPicture(X_VIDEO_BUTTON_PLAY,Y_VIDEO_BUTTON_PLAY,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PAUSE);
if(currPlayIndex == 2){
drawPicture(X_VIDEO_BUTTON_NEXT,Y_VIDEO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_VIDEO_NEXTI);
}
drawPicture(X_VIDEO_BUTTON_PREV,Y_VIDEO_BUTTON_PREV,FILE_ID_BUTTON,BUTTON_ID_VIDEO_PREV);
}
/*****************************************************************************************
播放指定文件ID的视频,指定开始播放的位置;
发送命令给GUI内核;
******************************************************************************************/
static void playVideo(u16 starts,u16 fileid)
{
memset(send_buffer,0,20);
send_buffer = 0x5A;
send_buffer = 0x01;
send_buffer = 0x00;// 使用文件中定义的播放速度;
send_buffer = 0x5A;// 开始音视频同步播放;
send_buffer = (starts>> 8 )& 0xFF;
send_buffer = (starts) & 0xFF;
send_buffer = (fileid>> 8 )& 0xFF;
send_buffer = (fileid) & 0xFF;
send_buffer = 0x00; // 视频画面中的起始位置;
send_buffer = 0x00;
send_buffer = 0x00;
send_buffer = 0x00;
send_buffer = 0x00; // 屏幕上的显示位置;
send_buffer = 0x6A;
send_buffer = 0x00;//y;
send_buffer = 0x0A;
send_buffer = 0x03; // 视频在屏幕上的显示宽度;
send_buffer = 0x20;
send_buffer = 0x01;//视频在屏幕上的显示高度;
send_buffer = 0xE0;
write_dgus_vp(0x00C8,send_buffer,10);
}
/*****************************************************************************************
处理音量进度条,使用多帧图片切换实现特效;
******************************************************************************************/
static void adjustVolume(void)
{
unsigned short av = 2048/20 * audioVolume;
memset(send_buffer,0,16);
send_buffer = (unsigned char)((av >> 8)& 0xFF);
send_buffer = (unsigned char)(av & 0xFF);
write_dgus_vp(0x00C5,send_buffer,1);
if(pageID == PAGE_ID_AUDIO){//如果是音乐播放界面,调用音乐进度条文件中的图片;
drawPartBKGPicture(X_AUDIO_POS_VOL,Y_AUDIO_POS_VOL,VOLUME_PIC_WIDTH,VOLUME_PIC_HEIGHT,X_AUDIO_POS_VOL,Y_AUDIO_POS_VOL,0);
drawPicture(X_AUDIO_POS_VOL,Y_AUDIO_POS_VOL,FILE_ID_AUDIO_VOLUME,audioVolume);
}
else{
drawPartBKGPicture(X_VIDEO_POS_VOL,Y_VIDEO_POS_VOL,VOLUME_PIC_WIDTH,VOLUME_PIC_HEIGHT,X_VIDEO_POS_VOL,Y_VIDEO_POS_VOL,1);
drawPicture(X_VIDEO_POS_VOL,Y_VIDEO_POS_VOL,FILE_ID_VIDEO_VOLUME,audioVolume);
}
}
/*****************************************************************************************
处理音乐播放进度条,使用多帧图片切换实现特效,并更新显示文字;
******************************************************************************************/
static void audioProgressDisplay(void)
{
int iframe;
int m0,s0,m1,s1;
char buf;
read_dgus_vp(0x00D2,&buf,4);
playPosition = ((int)buf) * 60 + (int)buf;
playTotalDuration = ((int)buf) * 60 + (int)buf;
if(playPosition > playTotalDuration){//过滤掉非正常数据;
//printf("audioProgressDisplay>>>pos=%d,total=%d\n",playPosition,playTotalDuration);
return;
}
iframe = (playPosition * 100)/ playTotalDuration;
if(iframe == oldProgressFrame){//当贴的图没有变化时不必要再刷新;
//printf("audioProgressDisplay>>>frame=%d,playPosition=%d,playTotalDuration=%d\n",iframe,playPosition,playTotalDuration);
return;
}
oldProgressFrame = iframe;
drawPicture(X_AUDIO_POS_PROGRESS,Y_AUDIO_POS_PROGRESS,FILE_ID_AUDIO_PROGRESS,iframe);
m0 = playTotalDuration/60;
s0 = playTotalDuration%60;
m1 = playPosition/60;
s1 = playPosition%60;
setBackground(0x80,0x80,0x80);
setForeground(0xFF,0xFF,0xFF);
sprintf(buf,"%02d:%02d/%02d:%02d",m1,s1,m0,s0);
drawText(X_POS_PTEXT,Y_POS_PTEXT,buf);
}
/*****************************************************************************************
处理视频播放进度条,使用多帧图片切换实现特效
******************************************************************************************/
static void videoProgressDisplay(void)
{
int iframe;
char buf;
read_dgus_vp(0x00D2,&buf,4);
playPosition = ((int)buf) * 60 + (int)buf;
playTotalDuration = ((int)buf) * 60 + (int)buf;
if(playPosition > playTotalDuration)
return;
iframe = (playPosition * 100)/ playTotalDuration;
if(iframe == oldProgressFrame)
return;
oldProgressFrame = iframe;
setDrawMode(0x01);
drawPicture(X_VIDEO_POS_PROGRESS,Y_VIDEO_POS_PROGRESS,FILE_ID_VIDEO_PROGRESS,iframe);
setDrawMode(0x00);
}
void processProgDisplay(void)
{
if(pageID == PAGE_ID_AUDIO)
audioProgressDisplay();
else if(pageID == PAGE_ID_VIDEO)
videoProgressDisplay();
}
版主补充:重要提示:该开源项目是配合20200425日期之前的UI版本内核固件制作,时间版本比较久远。建议用户只需参考os核下的8051c代码内容。
demo不要贸然下载到屏,不然可能会出现底图显示异常现象。
【开源】AIoT LCM平台开发自已的OS内核《三》
本帖最后由 lionel1203 于 2020-5-25 09:22 编辑接上:
六、参考代码分析
3、paint.c
/***************************************************************************************
版权所有 (C), 2020, 北京迪文科技有限公司
***************************************************************************************
文 件 名 : paint.c
版 本 号 :
作 者 :
生成日期 : 2020年4月23日
功能描述 : 通过GUI核实现图形界面输出;
修改历史 :
1.日 期 :
作 者 :
修改内容 :
****************************************************************************************/
#include <stdio.h>
#include<string.h>
#include "paint.h"
static u8 dr_ForeColor;
static u8 dr_BkgColor;
static u8 dr_LineWidth;
static u8 dr_FontId;//0(12X12),1(16x16),2(24x24),3(32X32);
static u8 dr_Mode;
extern u8 xdata send_buffer;
/*********************************************************************************************************
初始化绘图相关的参数,前景与背景颜色,线宽,字体,显示模式等参数初始化;
**********************************************************************************************************/
void initDraw(void)
{
memset(dr_ForeColor,0,4);
memset(dr_BkgColor,0,4);
dr_ForeColor = 0xFF;
dr_BkgColor = 0xFF;
dr_LineWidth = 0x02;
dr_FontId = 0x02;
dr_Mode = 0x00;
}
void check800CmdFinished(void)
{
u8 ckbuf;
do{
read_dgus_vp(0x1000,&ckbuf,1);
}while(ckbuf != 0x00 );
}
/*********************************************************************************************************
通过GUI核绘制文本到指定位置,使用当前字体,前景色和背景色;
x:位置
y:位置;
text:将显示的文字;
**********************************************************************************************************/
void drawText(int x,int y,char * text)
{
int len;
len = strlen(text) + 4;
send_buffer = 0x5A;
send_buffer = (u8)(len >> 8);
send_buffer = (u8)len & 0xFF;
switch(dr_FontId){
case 0:
send_buffer = 0x6E;
break;
case 1:
send_buffer = 0x54;
break;
case 2:
send_buffer = 0x6F;
break;
case 3:
send_buffer = 0x55;
break;
default:
return;
}
send_buffer = (u8)((x >> 8) & 0xFF);
send_buffer = (u8)(x & 0xFF);
send_buffer = (u8)((y >> 8) & 0xFF);
send_buffer = (u8)(y & 0xFF);
memcpy(&send_buffer,text,len - 4);
len = (len + 5)/2;
check800CmdFinished();
write_dgus_vp(0x1000,send_buffer,len);
}
/*********************************************************************************************************
通过GUI核显示图片,图片预处理成ICM文件,并存放在指定位置;
x:位置
y:位置;
libid:文件存放的指定位置,通过文件名数字决定;
picid:文件中的图标ID;
**********************************************************************************************************/
void drawPicture(int x,int y,int libid,int picid)
{
send_buffer = 0x5A;
send_buffer = 0x00;
send_buffer = 0x08;
send_buffer = 0x97;
send_buffer = (u8)(x >> 8)& 0xFF;
send_buffer = (u8)x & 0xFF;
send_buffer = (u8)( y>> 8 )& 0xFF;
send_buffer = (u8)y & 0xFF;
send_buffer = (u8)libid;
if(dr_Mode == 0x00){
send_buffer = (u8)0x00;
}
else
send_buffer = (u8)0x01;
send_buffer = ( picid>> 8 )& 0xFF;
send_buffer = picid & 0xFF;
check800CmdFinished();
write_dgus_vp(0x1000,send_buffer,6);
}
/**/
void switchPage(int id)
{
send_buffer = 0x5A;
send_buffer = 0x00;
send_buffer = 0x02;
send_buffer = 0x70;
send_buffer = 0x00;
send_buffer = (unsigned char)id;
check800CmdFinished();
write_dgus_vp(0x1000,send_buffer,3);
}
/*********************************************************************************************************
通过GUI核显示局部图片,图片预处理成ICM文件,并存放在指定位置,一般用于背景刷新;
sx,sy:在源图片中的起点位置
sw,sh:在源图片中要显示的区域高度和宽度;
dx,dy:显示在屏幕上的位置,左上角为(0,0);
picid:文件ID;
**********************************************************************************************************/
void drawPartBKGPicture(int sx,int sy,int sw,int sh,int dx,int dy,int picid)
{
sw += (sx - 1);
sh += (sy - 1);
send_buffer = 0x5A;
send_buffer = 0x00;
send_buffer = 0x0D;
send_buffer = 0x71;
send_buffer = (u8)picid;
send_buffer = (u8)(sx >> 8)& 0xFF;
send_buffer = (u8)sx & 0xFF;
send_buffer = (u8)( sy>> 8 )& 0xFF;
send_buffer = (u8)sy & 0xFF;
send_buffer = (u8)(sw >> 8)& 0xFF;
send_buffer = (u8)sw & 0xFF;
send_buffer = (u8)( sh>> 8 )& 0xFF;
send_buffer = (u8)sh & 0xFF;
send_buffer = (u8)(dx >> 8)& 0xFF;
send_buffer = (u8)dx & 0xFF;
send_buffer = (u8)( dy>> 8 )& 0xFF;
send_buffer = (u8)dy & 0xFF;
check800CmdFinished();
write_dgus_vp(0x1000,send_buffer,9);
}
/*********************************************************************************************************
通过GUI核绘制矩形,使用当前线宽,前景色与背景色;
x,y:起点位置
w,h:矩形的区域高度和宽度;
**********************************************************************************************************/
void drawRectangle(int x,int y,int w,int h)
{
}
/*********************************************************************************************************
通过GUI核绘制圆,使用当前线宽,前景色与背景色;
cx,cy:中心位置
radius:半径;
**********************************************************************************************************/
void drawCircle(int cx,int cy,int radius)
{
}
/*********************************************************************************************************
通过GUI核设置前景色;
r,g,b:颜色分量;
**********************************************************************************************************/
void setForeground(u8 r,u8 g,u8 b)
{
dr_ForeColor = r;
dr_ForeColor = g;
dr_ForeColor = b;
write_dgus_vp(0x0044,dr_ForeColor,2);
}
/*********************************************************************************************************
通过GUI核设置背景色;
r,g,b:颜色分量;
**********************************************************************************************************/
void setBackground(u8 r,u8 g,u8 b)
{
dr_BkgColor = r;
dr_BkgColor = g;
dr_BkgColor = b;
write_dgus_vp(0x0046,dr_BkgColor,2);
}
/*********************************************************************************************************
通过GUI核设置线宽;
width:线的宽度;
**********************************************************************************************************/
void setLineWidth(int width)
{
dr_LineWidth = width;
}
/*********************************************************************************************************
通过GUI核设置字体;
fontid:指定的字体;;
**********************************************************************************************************/
void setFont(int fontid)
{
dr_FontId = fontid;
}
/*********************************************************************************************************
通过GUI核显示模式;
mode:指定的显示模式;
**********************************************************************************************************/
void setDrawMode(int mode)
{
dr_Mode = (u8)mode;
}
4、cmd.c/***************************************************************************************
版权所有 (C), 2020, 北京迪文科技有限公司
***************************************************************************************
文 件 名 : cmd.c
版 本 号 :
作 者 :
生成日期 : 2020年4月23日
功能描述 : 串口2指令解析及执行;
修改历史 :
1.日 期 :
作 者 :
修改内容 :
****************************************************************************************/
#include <stdio.h>
#include<string.h>
#include "sys.h"
#include "uart.h"
#include "cmd.h"
#include "player.h"
/* Table of CRC values for high-order byte */
static const u8 code table_crc_hi = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};
/* Table of CRC values for low-order byte */
static const u8 code table_crc_lo = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
//发送命令用缓冲区;
u8 xdata send_buffer;
//系统配置信息;
static u8 sys_setting;
unsigned short getUShortFromBuf(u8 * buf);
/************************************************************************************************
初始化,读取命令执行中需要的系统配置信息;
*************************************************************************************************/
void initCMD(void)
{
u8buf;
read_dgus_vp(0x0002,buf,6);
sys_setting = buf;
printf("initCMD>>>sys_setting=\n");
UART2_SendBuffer(buf,12);
}
/*************************************************************************************************
添加帧尾到发送命令缓冲区;
cmdlen:放入到发送缓冲区中的开始偏移;
返回:添加完后,发送缓冲区大小;
**************************************************************************************************/
int addTail(int cmdlen)
{
send_buffer = 0xCC;
send_buffer = 0x33;
send_buffer = 0xC3;
send_buffer = 0x3C;
return cmdlen;
}
/*************************************************************************************************
添加长整型到发送命令缓冲区;
cmdlen:放入到发送缓冲区中的开始偏移;
返回:添加完后,发送缓冲区大小;
**************************************************************************************************/
int addLong(int cmdlen,long value)
{
u8 * cvp = (u8*)&value;
send_buffer = cvp;
send_buffer = cvp;
send_buffer = cvp;
send_buffer = cvp;
return cmdlen;
}
/*************************************************************************************************
添加2字节短整型到发送命令缓冲区;
cmdlen:放入到发送缓冲区中的开始偏移;
返回:添加完后,发送缓冲区大小;
**************************************************************************************************/
int addShort(int cmdlen,short value)
{
u8 * cvp = (u8*)&value;
send_buffer = cvp;
send_buffer = cvp;
return cmdlen;
}
/*************************************************************************************************
添加字符串到发送命令缓冲区;
cmdlen:放入到发送缓冲区中的开始偏移;
返回:添加完后,发送缓冲区大小;
**************************************************************************************************/
int addString(int cmdlen,const char * s)
{
while(*s != 0){
send_buffer = *s++;
if(cmdlen > 251 )
break;
}
return cmdlen;
}
/*************************************************************************************************
添加缓冲区到发送命令缓冲区;
cmdlen:放入到发送缓冲区中的开始偏移;
返回:添加完后,发送缓冲区大小;
**************************************************************************************************/
int addBuffer(int cmdlen,u8 * buff,int len)
{
memcpy(&send_buffer,buff,len);
return cmdlen+len;
}
/*************************************************************************************************
添加CRC校验数据到发送命令缓冲区;
cmdlen:放入到发送缓冲区中的开始偏移;
返回:添加完后,发送缓冲区大小;
**************************************************************************************************/
int addCRC(int cmdlen)
{
if( sys_setting & 0x80 ){
unsigned char tmp;
int i = 0;
u8 crc_hi = 0xFF;
u8 crc_lo = 0xFF;
while( i < cmdlen ){
tmp = crc_hi ^ send_buffer;
crc_hi = crc_lo ^ table_crc_hi;
crc_lo = table_crc_lo;
i++;
}
send_buffer = crc_hi;
send_buffer = crc_lo;
return cmdlen;
}
return cmdlen;
}
/*************************************************************************************************
对缓冲区中数据进行CRC校验;
buf:需校验的数据首地址;
len:需校验的数据长度;
返回:大于0校验成功;等于0没有校验;小于零校验失败;
**************************************************************************************************/
int checkCRC(u8 * buf,int len)
{
if( sys_setting & 0x80 ){
unsigned char tmp;
int i = 0;
u8 crc_hi = 0xFF;
u8 crc_lo = 0xFF;
if(len <= 6 )
return -1;
while( i < len - 6 ){
tmp = crc_hi ^ send_buffer;
crc_hi = crc_lo ^ table_crc_hi;
crc_lo = table_crc_lo;
i++;
}
if(crc_hi != buf ||
crc_lo != buf )
return -1;
return 1;
}
return 0;
}
/*************************************************************************************************
响应用户的握手请求,发送握手回应给用户;
**************************************************************************************************/
void responseUserShakehand(void)
{
int cmdlen;
u8buf;
send_buffer = 0xAA;
send_buffer = 0x00;
cmdlen = addString(2,"OK_V1.0");
send_buffer = 0x00;
send_buffer = 0x00;
read_dgus_vp(0x0002,buf,4);
cmdlen = addBuffer(cmdlen,&buf,5);
read_dgus_vp(0x0040,buf,2);
cmdlen = addBuffer(cmdlen,&buf,4);
cmdlen = addCRC(cmdlen);
cmdlen = addTail(cmdlen);
UART2_SendBuffer(send_buffer,cmdlen);
}
/*************************************************************************************************
处理调色板设置命令,根据接收到的数据,自动处理16BIT和24BIT数据;如果是16BIT还需要进行565转24位色;
buf:包括命令字的命令缓冲区首地址;
len:命令缓冲区中的数据长度,包含了帧尾;
**************************************************************************************************/
void processPaletteSetting(u8 * buf,int len)
{
u8 tb;
if( sys_setting & 0x80)
len -= 6;
else
len -= 4;
if(len > 6){
tb = 0x00;
memcpy(tb,&buf,3);
write_dgus_vp(0x0044,tb,2);
memcpy(tb,&buf,3);
write_dgus_vp(0x0046,tb,2);
}
else{
unsigned short c = getUShortFromBuf(&buf);
tb = 0x00;
tb = (c & 0xf800) >> 8;
tb = (c & 0x07e0) >> 3;
tb = (c & 0x001f) << 3;
write_dgus_vp(0x0044,tb,2);
c = getUShortFromBuf(&buf);
tb = (c & 0xf800) >> 8;
tb = (c & 0x07e0) >> 3;
tb = (c & 0x001f) << 3;
write_dgus_vp(0x0046,tb,2);
}
}
/*************************************************************************************************
处理显示间隔设置;
buf:包括命令字的命令缓冲区首地址;
len:命令缓冲区中的数据长度,包含了帧尾;
**************************************************************************************************/
void processDisplayGap(u8 * buf,int len)
{
u8 tb;
if(len < 3)
return;
read_dgus_vp(0x00042,tb,2);
tb = buf;
tb = buf;
write_dgus_vp(0x0042,tb,2);
}
/*************************************************************************************************
从缓冲区中获取短整型;
buf:缓冲区首地址;
返回:获取到的短整型数值;
**************************************************************************************************/
unsigned short getUShortFromBuf(u8 * buf)
{
unsigned short ret = buf;
ret <<= 8;
ret |= buf;
return ret;
}
/*************************************************************************************************
回应给用户CRC校验错误;
**************************************************************************************************/
void responseCRCError(void)
{
int cmdlen;
send_buffer = 0xAA;
send_buffer = 0xFF;
send_buffer = 0x01;
cmdlen = addCRC(3);
cmdlen = addTail(cmdlen);
UART2_SendBuffer(send_buffer,cmdlen);
}
/*************************************************************************************************
处理GUI内存直接写命令;
buf:包括命令字的命令缓冲区首地址;
len:命令缓冲区中的数据长度,包含了帧尾;
**************************************************************************************************/
void directWriteGUIMem(u8 * buf,int len)
{
int dlen;
unsigned short addr = 2 * getUShortFromBuf(buf+1);
if( sys_setting & 0x80 )
dlen = len - 6;//with crc;
else
dlen = len - 4;
dlen = (dlen - 3)/2;
write_dgus_vp(addr,&buf,dlen);
}
/*************************************************************************************************
处理GUI内存直接读取命令;
buf:包括命令字的命令缓冲区首地址;
返回:获取到的数据直接通过串口发送给用户;
**************************************************************************************************/
void directReadGUIMem(u8 * buf)
{
int len;
unsigned short addr = 2 * getUShortFromBuf(buf+1);
len = getUShortFromBuf(buf+3);
send_buffer = 0xAA;
send_buffer = 0xC2;
send_buffer = buf;
send_buffer = buf;
read_dgus_vp(addr,&send_buffer,len * 2);
len = len * 4 + 4;
len = addCRC(len);
len = addTail(len);
UART2_SendBuffer(send_buffer,len);
}
/*************************************************************************************************
处理默认的其它命令,直接把这些命令发送给GUI去处理;
buf:包括命令字的命令缓冲区首地址;
len:命令缓冲区中的数据长度,包含了帧尾;
**************************************************************************************************/
int route2GUIMemDefault(u8 * buf,int len)
{
int dlen;
if( sys_setting & 0x80 )//delete the tail and CRC,only send the datas and cmd;
len -= 6;
else
len -= 4;
dlen = len - 1;
send_buffer = 0x5A;
send_buffer = (u8)(dlen >> 8);
send_buffer = (u8)dlen & 0xFF;
memcpy(&send_buffer,buf,len);
if(len%2)
dlen = (len + 3)/2;
else
dlen = (len + 4)/2;
write_dgus_vp(0x1000,send_buffer,dlen);
return dlen;
}
/*************************************************************************************************
检查并发送触摸数据给串口用户;
**************************************************************************************************/
void checkAndSendTP2Uart(void)
{
u8 buf;
read_dgus_vp(0x0048,buf,4);
if(buf == 0x5A){//the tp is triggered;
processInput(&buf);
send_buffer = 0x00;
send_buffer = 0x00;
write_dgus_vp(0x0048,send_buffer,1);
if(sys_setting & 0x20){
int len;
u8 cmd = buf;
//filter by the sys_setting;
if(sys_setting & 0x40){//on
if(cmd != 0x78 && cmd != 0x79)
return;
}
else{
if( cmd != 0x72 && cmd != 0x73)
return;
}
if(sys_setting & 0x08){//not send 73/79;
if( cmd == 0x73 || cmd == 0x79)
return;
}
send_buffer = 0xAA;
send_buffer = cmd;
memcpy(&send_buffer,&buf,4);
len = 2 + buf;
len = addCRC(len);
len = addTail(len);
UART2_SendBuffer(send_buffer,len);
}
return;
}
}
【开源】AIoT LCM平台开发自已的OS内核《四》
本帖最后由 lionel1203 于 2020-5-25 09:22 编辑接上
六、参考代码分析
5、uart.c
/***************************************************************************************
版权所有 (C), 2020, 北京迪文科技有限公司
***************************************************************************************
文 件 名 : uart.c
版 本 号 :
作 者 :
生成日期 : 2020年4月23日
功能描述 : 串口函数
修改历史 :
1.日 期 :
作 者 :
修改内容 :
****************************************************************************************/
#include <stdio.h>
#include "sys.h"
#include "uart.h"
#include "cmd.h"
//串口2发送等待标志;
static u8 uart2_busy;
//串口2接收缓冲区数据总数;
static int recv_num;
//用于读取串口2的指令帧;
static intrecv_head;
//串口2接收缓冲区,其大小根据通讯协议帧的大小可调整;
static u8 xdata uart_buffer;
/***************************************************************************************
串口2的初始化,根据硬件配置参数,读取波特率,并设置给串口
****************************************************************************************/
void UART2_Init(void)
{
long brate = 0L;
unsigned short v;
//UART2配置
read_dgus_vp(0x0006,uart_buffer,2);
brate |= uart_buffer;
brate <<= 8;
brate |= uart_buffer;
brate <<= 8;
brate |= uart_buffer;
v = 1024 - (int)(5529600L/brate);
MUX_SEL|=0X40;
P0MDOUT|=0x10;
ADCON=0x80;
SCON0=0x50;
SREL0H = (v >> 8) & 0xFF;
SREL0L = v & 0xFF;
//SREL0H=0x03; //SREL0H/L = 1024 - 5529600/brate;
//SREL0L=0xD0;
IEN0|=0x10;
recv_num = 0;
recv_head = 0;
ES0=1;
EA=1;
uart2_busy=0;
}
/****************************************************************************************
通过串口2发送,按16进制值发送ASCII给终端,一般用于调试;
dat:发送的数据,在终端用2位16进制数表示;
****************************************************************************************/
void UART2_SendHex(u8 dat)
{
u8 xdata hi,lo;
hi = (dat >> 4) & 0x0F;
lo = dat & 0x0F;
if(hi > 9)
UART2_Sendbyte('A' + hi - 10 );
else
UART2_Sendbyte('0' + hi);
if(lo > 9)
UART2_Sendbyte('A' + lo - 10 );
else
UART2_Sendbyte('0' + lo );
}
/****************************************************************************************
通过串口2发送一字节数据给终端
dat:发送的数据;
****************************************************************************************/
void UART2_Sendbyte(u8 dat)
{
while(uart2_busy==1);
uart2_busy=1;
SBUF0 = dat;
}
/***************************************************************************************
通过串口发送连续内存区域给终端;
buf:缓冲区首地址;
len:发送的字节数;
****************************************************************************************/
void UART2_SendBuffer(u8 *buf,int len)
{
while(len--){
while(uart2_busy==1);
uart2_busy=1;
SBUF0 = *buf++;
}
}
/***********************************************************************************************
串口指令分发并执行;
串口指令通过串口中断方式接收到缓冲区时,当检查到帧结尾标志后,只有前面接收到的数据处理完成后,
中断函数才会把新接收的数据放到缓冲区中,而帧数据的分发和命令响应不能放在中断响应函数中;
************************************************************************************************/
void dispatchCommand(void)
{
u8 cmd;
if( recv_head != 1)
return;
if(checkCRC(uart_buffer,recv_num) < 0){
responseCRCError();
recv_num = 0;
recv_head = 0;//允许继续接收下一个命令;
return;
}
cmd = uart_buffer;
//printf("dispatchCommand>>>cmd=");
//UART2_SendHex(cmd);
//UART2_Sendbyte('\n');
switch(cmd){
case 0x00://握手;
responseUserShakehand();
break;
case 0x40://设置调色板;
processPaletteSetting(uart_buffer,recv_num);
break;
case 0x41://设置字符间距
processDisplayGap(uart_buffer,recv_num);
break;
case 0xC0://直接操作与GUI的共用缓冲区;
directWriteGUIMem(uart_buffer,recv_num);
break;
case 0xC2://直接从与GUI的共用缓冲区读取数据;
directReadGUIMem(uart_buffer);
break;
default://把命令打包传送给GUI执行;
route2GUIMemDefault(uart_buffer,recv_num);
break;
}
recv_num = 0;
recv_head = 0;//允许继续接收下一个命令;
}
/********************************************************************************************************
串口2中断响应函数;
从底层接收串口数据到接收缓冲区,并按帧数据保存到缓冲区,当recv_head == 1时,停止接收并忽略;
处理数据发送,当发送成功后把发送标志复位;
*********************************************************************************************************/
void UART2_ISR_PC(void) interrupt 4
{
EA=0;
if(RI0==1){
u8 res = SBUF0;
if(recv_head > 1){//save at buffer;
uart_buffer = res;
if(recv_num > 255){//the cmd is larger than the buffer,then discard this cmd;
recv_num = 0;
recv_head = 0;
}
switch(recv_head){
case 5:
if(res == 0xCC)
recv_head--;
break;
case 4:
if(res == 0x33)
recv_head--;
else
recv_head = 5;
break;
case 3:
if(res == 0xC3)
recv_head--;
else
recv_head = 5;
break;
case 2:
if(res == 0x3C)//fond a frame,discard next until the cmd is processed;
recv_head--;
else
recv_head = 5;
break;
default:
break;
}
}
else if(recv_head == 1){//wait for cmd processed;
}
else if( res == 0xAA )
recv_head = 5;
RI0=0;
}
if(TI0==1){
TI0=0;
uart2_busy=0;
}
EA=1;
}
6、sys.c
/******************************************************************************
版权所有 (C), 2020, 北京迪文科技有限公司
******************************************************************************
文 件 名 : sys.c
版 本 号 : V1.0
作 者 : gaolaihong
生成日期 : 2020.04.23
功能描述 : CPU及设备和定时器的初始化,以及相应访问接口;
修改历史 :
1.日 期 :
作 者 :
修改内容 :
******************************************************************************/
#include <T5LOS8051.H>
#include "sys.h"
#include "uart.h"
//记录开机以来的TICK数,1TICK = 10MS;
unsigned int sys_time_ticks;
//使用T2定时器,采用两级计数,定时器产生2MS的定时,然后形成10MS定时;
static unsigned char sys_tick_7200;
/***************************************************************************************************
检查指定DGUS变量地址的DATA3清零的话就退出
****************************************************************************************************/
static void wait_ok(unsigned int addr)
{
ADR_H=0x00;
ADR_M=(unsigned char)(addr>>8);
ADR_L=(unsigned char)(addr);
ADR_INC=0x00;
do{
for(addr=0;addr<1000;addr++) //释放变量空间一段时间
DATA2=DATA1;
RAMMODE=0xAF;
while(APP_ACK==0);
APP_EN=1;
while(APP_EN==1);
RAMMODE=0x00;
} while(DATA3!=0);
}
/*******************************************************************************************************
读取DGUS变量数据
addr=DGUS变量地址
*buf=数据返回指针
len=读取数据字长度
返回:无
********************************************************************************************************/
void read_dgus_vp(u32 addr,u8* buf,u16 len)
{
u8 i;
i=(unsigned char)(addr&0x01);
addr=addr/2;
ADR_H=0x00;
ADR_M=(unsigned char)(addr>>8);
ADR_L=(unsigned char)(addr);
ADR_INC=0x01;
RAMMODE=0xAF;
while(APP_ACK==0);
while(len>0){
APP_EN=1;
while(APP_EN==1);
if((i==0)&&(len>0)){
*buf++=DATA3;
*buf++=DATA2;
i=1;
len--;
}
if((i==1)&&(len>0)){
*buf++=DATA1;
*buf++=DATA0;
i=0;
len--;
}
}
RAMMODE=0x00;
}
/*******************************************************************************************************
写DGUS变量数据
addr=DGUS变量地址
*buf=写入数据指针
len=写入数据字长度
返回:无
********************************************************************************************************/
void write_dgus_vp(u32 addr,u8* buf,u16 len)
{
unsigned char i;
i=(unsigned char)(addr&0x01);
addr=addr/2;
ADR_H=0x00;
ADR_M=(unsigned char)(addr>>8);
ADR_L=(unsigned char)(addr);
ADR_INC=0x01;
RAMMODE=0x8F;
while(APP_ACK==0);
if(i && len>0){
RAMMODE=0x83;
DATA1=*buf++;
DATA0=*buf++;
APP_EN=1;
while(APP_EN==1);
len--;
}
RAMMODE=0x8F;
while(len>=2){
DATA3=*buf++;
DATA2=*buf++;
DATA1=*buf++;
DATA0=*buf++;
APP_EN=1;
while(APP_EN==1);
len=len-2;
}
if(len){
RAMMODE=0x8C;
DATA3=*buf++;
DATA2=*buf++;
APP_EN=1;
while(APP_EN==1);
}
RAMMODE=0x00;
}
/******************************************************************************************************
T5L OS CPU初始化
*******************************************************************************************************/
void INIT_CPU()
{
sys_time_ticks = 0;
sys_tick_7200 = 0;
CKCON=0x00;
T2CON=0x70;
DPC=0x00;
PAGESEL=0x01;
D_PAGESEL=0x02; //DATA RAM 08000-0FFFF
MUX_SEL=0x60; //把UART2、UART3 引出来,WDT关闭
RAMMODE=0x00; //不占用DGUS变量存储器
PORTDRV=0x01; //IO驱动强度 +/-8mA
IEN0=0x00; //关闭所有中断
IEN1=0x00;
IEN2=0x00;
IP0=0x00; //中断优先级用默认值
IP1=0x00;
P0=0x00; //IO配置,输出关闭,是不是输出取决于P0MDOUT
P1=0x00;
P2=0x00;
P3=0x00;
P0MDOUT=0x50; //P0 0101 0000
P1MDOUT=0x00; //P1 0000 0000
P2MDOUT=0x00; //P2 0000 0000
P3MDOUT=0x00; //P3 0000 0000
ADCON = 0x80; //UART2 配置 8N1 115200
SCON0 = 0x50;
SREL0H=0x03; //波特率=FCLK/64*(1024-SREL)
SREL0L=0xD0;
SCON1=0x90; //UART3 配置 8N1 115200
SREL1H=0x03; //波特率=FCLK/32*(1024-SREL1)
SREL1L=0xC8;
SCON2T=0x80; //UART4 配置 8N1 115200
SCON2R=0x80;
BODE2_DIV_H=0x00; //波特率=FCLK/8*DIV
BODE2_DIV_L=0xE0;
SCON3T=0x80; //UART5 配置 8N1 115200
SCON3R=0x80;
BODE3_DIV_H=0x00; //波特率=FCLK/8*DIV
BODE3_DIV_L=0xE0;
TMOD=0x11; //T0 16bit定时器
TH0=0x00;
TL0=0x00;
TR0=0;
TCON=0x05; //EX0 EX1是下跳沿中断
TH1=0x00; //T1 16bit定时器
TL1=0x00;
TR1=0;
T2CON=0x70; //T2 16bit Autoload模式
TH2=0x19;// 65536 - time(us) * 主频(MHZ)/12;
TL2=0x9a;
TRL2H=0x19;
TRL2L=0x9a;
IEN0|=0x20; //定时器2中断使能;
TR2=0x01;//定时器2开启;
}
sbit RTC_SDA = P3^3 ;
sbit RTC_SCL = P3^2 ;
static void SDA_IN(){
P3MDOUT=P3MDOUT&0xF7;
}
static void SDA_OUT()
{
P3MDOUT=P3MDOUT|0x0C;
}
//delay t uS
void delayus(unsigned char t)
{
char i;
while(t){
for(i=0;i<17;i++){
i=i;
}
t--;
}
}
void T2_IRQHandler() interrupt 5
{
TF2 = 0;
sys_tick_7200++;
if( sys_tick_7200 == 5 ){
sys_time_ticks++;
sys_tick_7200 = 0;
}
}
/*********************************************************************************************
获取自开机已来的TICKS数,每个TICK大约10MS左右;
*********************************************************************************************/
unsigned int getTickCount(void)
{
return sys_time_ticks;
}
static void i2cstart()
{
SDA_OUT();
RTC_SDA=1;
RTC_SCL=1;
delayus(15);
RTC_SDA=0;
delayus(15);
RTC_SCL=0;
delayus(15);
}
static void i2cstop()
{
SDA_OUT();
RTC_SDA=0;
RTC_SCL=1;
delayus(15);
RTC_SDA=1;
delayus(15);
SDA_IN();
}
static void mack()
{
SDA_OUT();
RTC_SDA=0;
delayus(5);
RTC_SCL=1;
delayus(5);
RTC_SCL=0;
delayus(5);
}
static void mnak()
{
SDA_OUT();
RTC_SDA=1;
delayus(5);
RTC_SCL=1;
delayus(5);
RTC_SCL=0;
delayus(5);
}
static void cack()
{
unsigned char i;
SDA_IN();
RTC_SDA=1;
delayus(5);
RTC_SCL=1;
delayus(5);
for(i=0;i<50;i++){
if(!RTC_SDA) break;
delayus(5);}
RTC_SCL=0;
delayus(5);
SDA_OUT();
}
static void i2cbw(unsigned char dat)
{
char i;
SDA_OUT();
for(i=0;i<8;i++){
if(dat&0x80) RTC_SDA=1;
else RTC_SDA=0;
dat=(dat<<1);
delayus(5);
RTC_SCL=1;
delayus(5);
RTC_SCL=0;
delayus(5);
}
cack();
}
static unsigned char i2cbr()
{
char i;
unsigned char dat;
SDA_IN();
for(i=0;i<8;i++){
delayus(5);
RTC_SCL=1;
delayus(5);
dat=(dat<<1);
if(RTC_SDA) dat=dat|0x01;
else dat=dat&0xFE;
RTC_SCL=0;
delayus(5);
}
return(dat);
}
static unsigned char bcd2Normal(unsigned char bcd)
{
unsigned char n,m;
n = bcd / 10;
m = bcd % 10;
return n * 16 + m;
}
static unsigned char normal2BCD(unsigned char no)
{
unsigned char n,m;
n = no / 16;
m = no % 16;
return n * 10 + m;
}
static void rtc_settime(u8 *buf)
{
i2cstart();
i2cbw(0x64);
i2cbw(0x30);
i2cbw(0x00);
i2cstop();
i2cstart();
i2cbw(0x64);
i2cbw(0x1C);
i2cbw(0x48);
i2cbw(0x00);
i2cbw(0x40);
i2cbw(0x10);
i2cstop();
i2cstart();
i2cbw(0x64);
i2cbw(0x10);
i2cbw(buf);
i2cbw(buf);
i2cbw(buf);
i2cbw(buf);
i2cbw(buf);
i2cbw(buf);
i2cbw(buf);
i2cstop();
i2cstart();
i2cbw(0x64);
i2cbw(0x1E);
i2cbw(0x00);
i2cbw(0x10);
i2cstop();
}
/*********************************************************************************************
初始化RTC硬件,如果发现掉电,则RTC设置为2017年1月1日星期一,零时零分零秒;
**********************************************************************************************/
void INIT_RTC()
{
unsigned char i;
i2cstart();
i2cbw(0x64);
i2cbw(0x1d);
i2cstop();
i2cstart();
i2cbw(0x65);
i=i2cbr();
mack();
i2cbr();
mnak();
i2cstop();
if((i&0x02)==0x02){
u8 buf;
buf = 0x17;
buf = 0x01;
buf = 0x01;
buf = 0x01;
buf = 0x00;
buf = 0x00;
buf = 0x00;
rtc_settime(buf);
}
}
/***********************************************************************************************
检查寄存器并设置RTC寄存器的初始值
************************************************************************************************/
void checkAndSetRTC(void)
{
unsigned char i;
u8 buf;
read_dgus_vp(0x0050,buf,4);
if( buf == 0x5A ){
for( i = 1; i < 4; i++){
buf = bcd2Normal(buf);
}
for( i = 5; i < 8; i++){
buf = bcd2Normal(buf);
}
buf = 1 << buf;
rtc_settime(buf);
}
}
/***************************************************************************************************
读取RTC寄存器的值,并写入数据缓冲区,供GUI或串口指令查询。
此函数一般被定时调用,间隔一般要小于500MS。
****************************************************************************************************/
void rdtime(void)
{
unsigned char rtcdata;
unsigned char i,n,m;
i2cstart();
i2cbw(0x64);
i2cbw(0x10);
i2cstop();
i2cstart();
i2cbw(0x65);
for(i=7;i>1;i--){
rtcdata=i2cbr();
mack();
}
rtcdata=i2cbr();
mnak();
i2cstop();
for(i=1;i<4;i++){ //
rtcdata = normal2BCD(rtcdata);
}
for(i=5;i<8;i++){
rtcdata = normal2BCD(rtcdata);
}
n=0;
m=rtcdata;
for(i=1;i<8;i++){
if(m&0x01)break;
n++;
m=(m>>1);
}
rtcdata=n;
rtcdata=0x5A;
write_dgus_vp(0x004C,rtcdata,0x04);
}
/********************************************************************************************************
微秒延时函数
t:延时值;
返回:无;
**********************************************************************************************************/
void delay_us(unsigned int t)
{
char i;
while(t){
for(i=0;i<17;i++)
i=i;
t--;
}
}
【开源】AIoT LCM平台开发自已的OS内核《二》
本帖最后由 lionel1203 于 2020-5-25 09:38 编辑接上六,参考代码分析
2、main.c(主循环)
/***************************************************************************************
版权所有 (C), 2020, 北京迪文科技有限公司
***************************************************************************************
文 件 名 : main.c
版 本 号 :
作 者 :
生成日期 : 2020年4月23日
功能描述 : 程序主循环,主控入口;
修改历史 :
1.日 期 :
作 者 :
修改内容 :
****************************************************************************************/
#include <T5LOS8051.H>
#include <stdio.h>
#include "sys.h"
#include "uart.h"
#include "cmd.h"
#include "paint.h"
#include "player.h"
//触摸数据检查间隔,100MS;
#define TP_CHECK_TIME 10
//显示刷新检查间隔,一般用于进度条刷新;
#define DISP_REFRESH_TIME 50
//RTC设置检查间隔,2秒;
#define RTC_SETTIME 200
//RTC时间更新间隔,400MS;
#define RTC_READTIME 40
//保存了上次检查时间;
static unsigned int tp_checktime;
static unsigned int rtc_checksetting;
static unsigned int rtc_readtime;
static unsigned int disp_refreshtime;
/*************************************************************************************************
修改标准库的putchar函数,直接输出给串口2,用于调试;
**************************************************************************************************/
char putchar (char c){
if(c == '\n')
UART2_Sendbyte(0x0D);
UART2_Sendbyte(c);
return c;
}
/***************************************************************************************************
比较时间的间隔大小;
t0:开始时间;
t1:结束时间;
返回:开始到续束时间之间的时间长度;
****************************************************************************************************/
static unsigned int tick_diff_time(unsigned int t0,unsigned int t1)
{
if(t1 >= t0)
return t1 - t0;
else
return (0xFFFF - t0 + t1 + 1);
}
extern unsigned int sys_time_ticks;
/***************************************************************************************************
The main C function.Program execution starts
here after stack initialization.
****************************************************************************************************/
void main (void) {
//初始化;
INIT_CPU();
INIT_RTC();
UART2_Init();
initCMD();
initDraw();
initPlayer();
tp_checktime = 0;
rtc_checksetting = 0;
rtc_readtime = 0;
disp_refreshtime = 0;
while(1){
dispatchCommand();//分发串口命令;
if(tick_diff_time(tp_checktime,sys_time_ticks) > TP_CHECK_TIME){//检查触摸数据时间到;
checkAndSendTP2Uart();
tp_checktime = sys_time_ticks;
}
if(tick_diff_time(rtc_checksetting,sys_time_ticks) > RTC_SETTIME){//检查RTC设置命令时间到;
checkAndSetRTC();
rtc_checksetting = sys_time_ticks;
}
if(tick_diff_time(rtc_readtime,sys_time_ticks) > RTC_READTIME){//读取RTC时间值
rdtime();
rtc_readtime = sys_time_ticks;
}
if(tick_diff_time(disp_refreshtime,sys_time_ticks) > DISP_REFRESH_TIME){//进度条刷新
processProgDisplay();
disp_refreshtime = sys_time_ticks;
}
}
}
lionel1203 发表于 2020-5-25 09:26
接上六,参考代码分析
2、main.c(主循环)
DWIN_SET烧录文件中,由于尺寸限制,无法打包电影和音乐的演示文件,请客户参考代码中的文件序号,使用AllToolForAIOT工具打包生成自已的音视频文件。 static const unsigned char code m_audioID = { 0x50,0x6C,0x84 };//音乐文件ID,共3个;
static const unsigned char code m_videoID = { 186,155, 172};//电影伴音文件,共3个;
static const unsigned char code m_videoAudioID = { 181,152,168 };//电影视频文件,共3个。 还要请提醒大家的是,示例工程对应的是AIoT LCM平台,采用主频353.8944MHZ主频,显示分辨率为1024X600的设备,其它分辨率或平台如果不修改是无法正常工作的。 基于DMG19108C156_03W进行二次开发示例演示
问题:
1、DMG19108C156_03W是否支持二次开发?
2、如果支持,内嵌用户OS如何与屏进行交互数据?
最好能给举个例子,如进行一个数值的显示(实时温度值)
以上,谢谢! 这个驱动程序主要是控制那一块? 头文件呢:dizzy:
页:
[1]
2