lionel1203 发表于 2020-5-7 11:59:35

【开源】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不要贸然下载到屏,不然可能会出现底图显示异常现象。



lionel1203 发表于 2020-5-7 15:29:41

【开源】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;
      }
}



lionel1203 发表于 2020-5-7 15:36:53

【开源】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--;
      }
}



lionel1203 发表于 2020-5-25 09:26:59

【开源】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:41:36

lionel1203 发表于 2020-5-25 09:26
接上六,参考代码分析
2、main.c(主循环)

DWIN_SET烧录文件中,由于尺寸限制,无法打包电影和音乐的演示文件,请客户参考代码中的文件序号,使用AllToolForAIOT工具打包生成自已的音视频文件。

lionel1203 发表于 2020-5-25 09:43:43

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个。

lionel1203 发表于 2020-5-25 09:50:06

还要请提醒大家的是,示例工程对应的是AIoT LCM平台,采用主频353.8944MHZ主频,显示分辨率为1024X600的设备,其它分辨率或平台如果不修改是无法正常工作的。

fl373410295 发表于 2020-8-31 22:41:10

基于DMG19108C156_03W进行二次开发示例演示
问题:
1、DMG19108C156_03W是否支持二次开发?
2、如果支持,内嵌用户OS如何与屏进行交互数据?
最好能给举个例子,如进行一个数值的显示(实时温度值)
以上,谢谢!

lihui163 发表于 2020-9-10 13:29:00

这个驱动程序主要是控制那一块?

lanlanzhilian 发表于 2021-2-27 19:07:31

头文件呢:dizzy:
页: [1] 2
查看完整版本: 【开源】AIoT LCM平台开发自已的OS内核《一》