Слияние кода завершено, страница обновится автоматически
/*
运行:sudo ./LcdPlayer
编译:gcc LcdPlayer.c -o LcdPlayer -L lib -l wiringPi (需已安装wiringPi)
by:WuSiYu
tieba ID: laowu2012007
*/
#include <stdio.h> //标准库
#include <stdlib.h>
#include <string.h>
#include <iconv.h> //字符编码转换库
#include <sys/timeb.h> //时间库
#include <wiringPi.h> //rasPi的GPIO库
#define VIDEO_DATA_FILE "./video.data" //视频数据文件地址
#define DELAY_BEFORE_START 2.4 //视频开始播放前的延时,根据你的播放器的音乐载入速度而定:
//参考值:使用mplayer播放器时,Pi 1设为3.2,Pi 2设为2.4
#define LCD_RS 4 //显示屏控制线
#define LCD_RW 5
#define LCD_EN 1
#define D1 30 //显示屏数据线
#define D2 21
#define D3 22
#define D4 23
#define D5 24
#define D6 25
#define D7 26
#define D8 27
char UTF8_TO_GB2312_OUT_BUFF[255];
int THIS_LINE_DATA[768];
long should_played_frames=0, real_played_frames=0, jumped_frames=0;
int isDebug=0;
struct timeb tp;
FILE *DataFileFp;
/*===================================================================
功能:编码转换
输入:UTF8
输出:GB2312
====================================================================*/
int Code_Convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen){
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;
cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
iconv_close(cd);
return 0;
}
int UTF8_to_GB2312(char *inbuf,int inlen,char *outbuf,int outlen){
return Code_Convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
/*===================================================================
功能:总线写入
输入:十六进制数据
输出:无
====================================================================*/
void bus_write(unsigned char data){
int t[10];
int f=0,i=0,d=data;
//进制转换
for(i=0;i<8;i++){
t[i]=data%2;
data=data/2;
}
//输出
digitalWrite(D1,t[0]);
digitalWrite(D2,t[1]);
digitalWrite(D3,t[2]);
digitalWrite(D4,t[3]);
digitalWrite(D5,t[4]);
digitalWrite(D6,t[5]);
digitalWrite(D7,t[6]);
digitalWrite(D8,t[7]);
}
/*===================================================================
功能:检查LCD忙状态
输入:无
输出:lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。
====================================================================*/
void chk_busy(){//检查忙位
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,1);
digitalWrite(LCD_EN,1);
bus_write(0xff);
pinMode(D8, INPUT);
while(digitalRead(D8));
pinMode(D8, OUTPUT);
digitalWrite(LCD_EN,0);
}
/*====================================================================
功能:写命令
输入:8位数据
输出:无
=====================================================================*/
void WriteCmd_LCD12864(unsigned char cmdcode){
chk_busy();
digitalWrite(LCD_RS,0);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_EN,1);
bus_write(cmdcode);
digitalWrite(LCD_EN,0);
}
/*====================================================================
功能:写数据
输入:8位数据
输出:无
=====================================================================*/
void WriteData_LCD12864(unsigned char Dispdata){
chk_busy();
digitalWrite(LCD_RS,1);
digitalWrite(LCD_RW,0);
digitalWrite(LCD_EN,1);
bus_write(Dispdata);
digitalWrite(LCD_EN,0);
}
/*==========================================================================
功能:发送字符串
输入:地址,字符串
输出:无
===========================================================================*/
void WriteWord_LCD12864(unsigned char a,unsigned char *d){//向LCD指定位置发送一个字符串,长度64字符之内。
unsigned char *s;
UTF8_to_GB2312(d,strlen(d),UTF8_TO_GB2312_OUT_BUFF,255);
s=UTF8_TO_GB2312_OUT_BUFF;
WriteCmd_LCD12864(a);
while(*s>0){
WriteData_LCD12864(*s);
s++;
}
}
/*==========================================================================
功能:发送字符串2
输入:字符串
输出:无
===========================================================================*/
void WriteWord_LCD12864_2(unsigned char *d){//向LCD发送一屏字符串,长度64字符之内。
int i=0;
unsigned char *s;
UTF8_to_GB2312(d,strlen(d),UTF8_TO_GB2312_OUT_BUFF,255);
s=UTF8_TO_GB2312_OUT_BUFF;
WriteCmd_LCD12864(0x80);
while(*s>0){
WriteData_LCD12864(*s);
s++;
i++;
if(i==16){
WriteCmd_LCD12864(0x90);
}
if(i==32){
WriteCmd_LCD12864(0x88);
}
if(i==48){
WriteCmd_LCD12864(0x98);
}
}
}
/*==========================================================================
功能:清屏
输入:颜色1,颜色2
输出:无
===========================================================================*/
void Clean_LCD12864(unsigned char c,unsigned char d){
unsigned char l,r;
WriteCmd_LCD12864(0x34);
for(l=0;l<32;l++){
WriteCmd_LCD12864(0x80+l);
WriteCmd_LCD12864(0x80);
for(r=0;r<16;r++){
WriteData_LCD12864(c);
WriteData_LCD12864(d);
}
}
}
/*==========================================================================
功能:初始化LCD
输入:无
输出:无
===========================================================================*/
void Init_LCD12864(void){ //初始化LCD屏
pinMode(D1, OUTPUT); //设置GPIO为输出模式
pinMode(D2, OUTPUT);
pinMode(D3, OUTPUT);
pinMode(D4, OUTPUT);
pinMode(D5, OUTPUT);
pinMode(D6, OUTPUT);
pinMode(D7, OUTPUT);
pinMode(D8, OUTPUT);
pinMode(LCD_RS, OUTPUT);
pinMode(LCD_RW, OUTPUT);
pinMode(LCD_EN, OUTPUT);
WriteCmd_LCD12864(0x38); //选择8bit数据流
delay(20);
WriteCmd_LCD12864(0x01); //清除显示,并且设定地址指针为00H
delay(20);
WriteCmd_LCD12864(0x0c); //开显示(无游标、不反白)
delay(20);
}
/*==========================================================================
功能:将 全局数组THIS_LINE_DATA 中的一帧的数据显示在显示屏上
输入:无
输出:无
===========================================================================*/
void Display_OneFrame(void){
unsigned char l,r;
if(isDebug){
ftime(&tp);
printf("%d-", tp.millitm);
}
for(l=0;l<32;l++){
WriteCmd_LCD12864(0x80+l);
WriteCmd_LCD12864(0x80+1);
for(r=0;r<6;r++){
WriteData_LCD12864(THIS_LINE_DATA[12*l+r*2]);
WriteData_LCD12864(THIS_LINE_DATA[12*l+r*2+1]);
}
}
for(l=0;l<32;l++){
WriteCmd_LCD12864(0x80+l);
WriteCmd_LCD12864(0x88+1);
for(r=0;r<6;r++){
WriteData_LCD12864(THIS_LINE_DATA[12*32+12*l+r*2]);
WriteData_LCD12864(THIS_LINE_DATA[12*32+12*l+r*2+1]);
}
}
if(isDebug){
ftime(&tp);
printf("%d\n", tp.millitm);
}
}
/*==========================================================================
功能:从文件里读取一帧并放入 全局数组THIS_LINE_DATA 中
输入:无
输出:无
===========================================================================*/
void Load_OneFrame(void){
int i=0, s=0, value_number=0, n=0;
char this_line_text[3200];
char one_value_buf[3];
if(isDebug){
ftime(&tp);
printf("%d-", tp.millitm);
}
if(!fgets(this_line_text,3200,DataFileFp)){
printf("At EOL, abort\n");
printf("%d frames jumped, Total %d frames. \n", jumped_frames, should_played_frames);
printf("Average fps: %f\n", 30.0 * (should_played_frames - jumped_frames) / should_played_frames );
exit(0);
}
if(isDebug){
ftime(&tp);
printf("%d-", tp.millitm);
}
n=strlen(this_line_text);
for(i=0;i<n;i++){ //遍历这行的每个字符
if(this_line_text[i]=='-'){
THIS_LINE_DATA[value_number]=atoi(one_value_buf);
one_value_buf[0]=' '; one_value_buf[1]=' '; one_value_buf[2]=' ';
s=0;value_number++;
}else{
one_value_buf[s]=this_line_text[i];
s++;
}
}
}
/*==========================================================================
功能:跳过一帧
输入:无
输出:无
===========================================================================*/
void Jump_OneFrame(void){
char this_line_text[3200];
fgets(this_line_text,3200,DataFileFp);
}
/*==========================================================================
功能:煮含树 o( ̄ヘ ̄o)
输入:无
输出:无
===========================================================================*/
int main (int args, char *argv[]){
int time_last_frame_ms=0;
long time_last_frame_s=0, later_ms;
wiringPiSetup();
Init_LCD12864();
if(argv[1]){
isDebug=1;
printf("Start-ReadFile-Process-Display\n");
}
WriteCmd_LCD12864(0x01);
WriteWord_LCD12864(0x80,"Badapple on ");
WriteWord_LCD12864(0x90,"rasPi + LCD12864");
WriteWord_LCD12864(0x88," ");
WriteWord_LCD12864(0x98," By WuSiYu");
delay(DELAY_BEFORE_START*1000);
WriteCmd_LCD12864(0x01);
WriteCmd_LCD12864(0x36);
Clean_LCD12864(0x00,0x00);
WriteCmd_LCD12864(0x36);
DataFileFp=fopen(VIDEO_DATA_FILE,"r");
ftime(&tp);
time_last_frame_s = tp.time;
time_last_frame_ms = tp.millitm;
while(1){
ftime(&tp);
if(time_last_frame_ms > tp.millitm){ //如果“进位”了
later_ms = (tp.time - time_last_frame_s)*1000 - (time_last_frame_ms - tp.millitm); //计算距上一帧过去的毫秒数
should_played_frames += (later_ms/1000)*30 + (later_ms%1000)/33; //计算此时“理论上”应该播放了多少帧
time_last_frame_ms += (later_ms%1000) - (later_ms%1000)%33; //更新上一帧播放时的时间
time_last_frame_s = tp.time-1;
if(time_last_frame_ms > 1000){
time_last_frame_ms -= 990;
time_last_frame_s++;
}
}else{
if(tp.millitm-time_last_frame_ms >= 33 || tp.time-time_last_frame_s > 1){
should_played_frames += (tp.time - time_last_frame_s)*30 + (tp.millitm - time_last_frame_ms)/33;
time_last_frame_ms += (tp.millitm - time_last_frame_ms) - (tp.millitm - time_last_frame_ms)%33;
time_last_frame_s = tp.time;
}
}
if(should_played_frames > real_played_frames){
while(should_played_frames > real_played_frames+1){
Jump_OneFrame();
real_played_frames++;
jumped_frames++;
}
Load_OneFrame();
Display_OneFrame();
real_played_frames++;
}
delay(1);
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )