Files
player/Project_App_Calendar/App_Src/win/mywin_user_train.c
2025-07-05 19:47:28 +08:00

366 lines
7.8 KiB
C

#include "mywin_inc.h"
#include "mywin_user_train.h"
#include "arm_math.h"
#include "qmc6310.h"
#include "math.h"
#define WIN_TRAIN_TYPE "WIN_TrainStruct"
WIN_TrainStruct *WIN_CreatTrain (WIN_WindowStruct *base,
void (*msgLoop)(struct _WIN_WindowStruct *win,WIN_MsgStruct *msg),
int x,int y,int x_size,int y_size)
{
//重设消息循环
if (msgLoop==0)
{
msgLoop=(void (*)(struct _WIN_WindowStruct *win,WIN_MsgStruct *msg))TRAIN_DefaultMsgLoop;
}
WIN_TrainStruct *ret=mymalloc (sizeof ( WIN_TrainStruct));
//调用父类的构造函数
if (ret)
{
mymemset (ret,0,sizeof ( WIN_TrainStruct));
// if (0==WIN_CreatWindowExt((WIN_WindowStruct *)ret,base,msgLoop,x,y,x_size,y_size))
if (0==WIN_CreatTouchEx((WIN_TouchWinStruct *)ret,base,msgLoop,x,y,x_size,y_size))
{
//创建失败
myfree (ret);
ret=0;
}
else
{
((WIN_WindowStruct *)ret)->winType=WIN_TRAIN_TYPE;
((WIN_WindowStruct *)ret)->intercept=1;//不发送按键消息到父窗口
((WIN_WindowStruct *)ret)->color=0xffffff;
//构造一个
ret->color1=0xff6600; //橙色
ret->color2=0x887b6e; //灰白
ret->timerId= WIN_CreatTimer ((WIN_WindowStruct *)ret,100);
ret->timer_20ms=WIN_CreatTimer ((WIN_WindowStruct *)ret,20);
qmc6310_init();
ret->fitt_on=1;
for(int i=0;i<WIN_GET_ARRAY_SIZE(ret->kal);i++)
{
kalman_init(&ret->kal[i]);
}
}
}
return ret;
}
//更新数据
void TRAIN_DataUpdata (WIN_TrainStruct *train,TRAIN_Struct *s)
{
//使用内存复制的方法复制结构体
// mymemcpy (& train->data,s,sizeof (TRAIN_Struct));
}
//设置背景图片
void TRAIN_SetBackPic (WIN_TrainStruct *train,WIN_PicStruct *pic)
{
WIN_SetBackPic ((WIN_WindowStruct *)train,pic);
}
//处理按键消息
int TRAIN_KeyBord (WIN_TrainStruct *train,WIN_KeyStruct *k)
{
if (k->shortPress&KEY_VALUE_HOME)
{
((WIN_WindowStruct *)train)->deleteWindow((WIN_WindowStruct *)train);
}
return 0;
}
//由毒素得到文字
static char *GetTxtByAngle (int angle)
{
while (angle<0) angle+=360;
while (angle>360) angle-=360;
if ((angle>=360-45/2)||(angle<=45/2))
{
return "";
}
else if ((angle>45/2)&&(angle<=45+45/2))
{
return "东北";
}
else if ((angle>45+45/2)&&(angle<=90+45/2))
{
return "";
}
else if ((angle>90+45/2)&&(angle<=135+45/2))
{
return "东南";
}
else if ((angle>135+45/2)&&(angle<=180+45/2))
{
return "";
}
else if ((angle>180+45/2)&&(angle<=225+45/2))
{
return "西南";
}
else if ((angle>225+45/2)&&(angle<=270+45/2))
{
return "西";
}
else if ((angle>270+45/2)&&(angle<=315+45/2))
{
return "西北";
}
return 0;
}
//作为指南针的绘制函数
void TRAIN_CompassPaint (WIN_TrainStruct *train)
{
int x=0;
int y=0;
int x_size=((WIN_WindowStruct *)train)->x_size;
int y_size=((WIN_WindowStruct *)train)->y_size;
//绘制背景
WIN_PaintBackGround ((WIN_WindowStruct *)train);
//显示标题
int img_x=x+25;
int img_y=y;
int img_xsize=0;
int img_ysize=0;
int head_ysize=45;
WIN_SetLcdColor (((WIN_WindowStruct *)train)->color);
if (train->icon)
{
WIN_GetImageSize (train->icon,&img_xsize,&img_ysize);
if (img_ysize>head_ysize) img_ysize=head_ysize;
WIN_DrawImagByAlpha (img_x,img_y+head_ysize/2-img_ysize/2, img_xsize,img_ysize,train->icon,WIN_GetLcdColor16());
img_xsize+=10;
}
WIN_DrawTxtAt (train->title,img_x+img_xsize,y+head_ysize/2-WIN_GetFontHight()/2);
int r_ex=250/2;
int r_in=r_ex-10;
//画外圈
WIN_SetLcdColor (((WIN_WindowStruct *)train)->color);
WIN_DrawCircle (x_size/2,y_size/2,r_ex);
//画刻度
float angle=train->angle;
for (int i=0;i<8;i++)
{
float sinx=0;
float cosx=0;
arm_sin_cos_f32 (angle,&sinx,&cosx);
angle+=45.0f;
int x1=x_size/2-sinx*r_ex;
int y1=y_size/2-cosx*r_ex;
int x2=x_size/2-sinx*r_in;
int y2=y_size/2-cosx*r_in;
WIN_DrawLineAA (x1,y1,x2,y2,4);
int x_txt=(x_size/2-sinx*(r_in-WIN_GetFontHight()/2));//-WIN_GetFontHight()/2;
int y_txt=(y_size/2-cosx*(r_in-WIN_GetFontHight()/2))-WIN_GetFontHight()/2;
WIN_SetLcdColor (((WIN_WindowStruct *)train)->color);
if (i==0)//北方
{
WIN_SetLcdColor (train->color1);
WIN_DrawTxtHCenterAt ("N",x_txt,y_txt);
WIN_SetLcdColor (((WIN_WindowStruct *)train)->color);
}
else if (i==2)//西方
{
WIN_DrawTxtHCenterAt ("W",x_txt,y_txt);
}
else if (i==4)//南方
{
WIN_DrawTxtHCenterAt ("S",x_txt,y_txt);
}
else if (i==6)//东方
{
WIN_DrawTxtHCenterAt ("E",x_txt,y_txt);
}
}
//画箭头
POINT_Struct point[3]={0};
point[0].x=x_size/2;
point[0].y=y_size/2-r_in+18;
point[1].x=x_size/2-5;
point[1].y=y_size/2-r_in+23;
point[2].x=x_size/2+5;
point[2].y=y_size/2-r_in+23;
WIN_SetLcdColor (train->color1);
WIN_FillPolygon (point,3);
//画内圈
r_in-=25;
WIN_DrawCircle (x_size/2,y_size/2,r_in);
//显示方位
char txt[20]={0};
WIN_SetLcdColor (((WIN_WindowStruct *)train)->color);
WIN_DrawTxtHCenterAt (GetTxtByAngle(train->angle),x_size/2,y_size/2-WIN_GetFontHight());
sprintf (txt," %.0f°",train->angle);
WIN_DrawTxtHCenterAt (txt,x_size/2,y_size/2);
}
//默认绘制函数
void TRAIN_DefaultPaint (WIN_TrainStruct *train)
{
int x=0;
int y=0;
int x_size=((WIN_WindowStruct *)train)->x_size;
int y_size=((WIN_WindowStruct *)train)->y_size;
char txt_buff[20]={0};
int old_font_type=0;
//绘制背景
WIN_PaintBackGround ((WIN_WindowStruct *)train);
WIN_SetLcdColor (((WIN_WindowStruct *)train)->color);
}
void TRAIN_Refresh(WIN_TrainStruct *axis)
{
//椭圆拟合
if(axis->ell.num>10&&axis->ell.num%10==0)
{
if(axis->fitt_on)
ellipsoid_fitting(&axis->ell);
}
//计算校准后的磁力值
if(axis->ell.a!=0.0f)
axis->fitt_raw[0]=(axis->mag_raw[0]-axis->ell.x)/axis->ell.a;
if(axis->ell.b!=0.0f)
axis->fitt_raw[1]=(axis->mag_raw[1]-axis->ell.y)/axis->ell.b;
if(axis->ell.c!=0.0f)
axis->fitt_raw[2]=(axis->mag_raw[2]-axis->ell.z)/axis->ell.c;
//计算模
axis->mod=sqrtf(axis->fitt_raw[0]*axis->fitt_raw[0]+axis->fitt_raw[1]*axis->fitt_raw[1]+axis->fitt_raw[2]*axis->fitt_raw[2]);
//判断是否需要重新校准
if(axis->mod-1>=-0.1f&&axis->mod-1<=0.1f)
{
axis->suss_num++;
if(axis->suss_num>50) axis->fitt_on=0;
}
else
{
axis->suss_num=0;
axis->fitt_on=1;
}
//计算方向
axis->angle=atan2(axis->fitt_raw[1],axis->fitt_raw[0])*180.0f/3.14159f;
//调整90度
axis->angle+=90.0f;
if(axis->angle>180.0f) axis->angle-=360.0f;
}
//默认消息处理函数
void TRAIN_DefaultMsgLoop (WIN_TrainStruct *train,WIN_MsgStruct *msg)
{
WIN_MoveStruct *m=0;
WIN_TouchStruct *t=0;
TRAIN_Struct *s=0;
switch (msg->msg)
{
case WIN_MSG_PAINT:
if(train->paint)
train->paint(train);
break;
case WIN_MSG_TIMER:
if (msg->data.v==train->timerId)
{
TRAIN_Refresh(train);
WIN_SetInvalidWhenTop ((WIN_WindowStruct *)train);
}
else if(msg->data.v==train->timer_20ms)
{
qmc6310_read_mag_xyz(train->mag_raw);
for(int i=0;i<WIN_GET_ARRAY_SIZE(train->kal);i++)
{
train->mag_raw[i]=kalman_filter(&train->kal[i],train->mag_raw[i]);
}
if(train->fitt_on)
ellipsoid_add_point(&train->ell,train->mag_raw[0],train->mag_raw[1],train->mag_raw[2]);
}
break;
case WIN_MSG_KEY:
TRAIN_KeyBord (train,msg->data.p);
break;
//状态栏接收的外部消息是为 TRAIN_Struct 类型的结构体
case WIN_MSG_EXTMSG:
s=msg->data.p;
TRAIN_DataUpdata (train,s);
WIN_SetInvalidWhenTop ((WIN_WindowStruct *)train);
break;
default:
WIN_DefaultMsgLoop((WIN_WindowStruct *)train,msg);
break;
}
}
//#include "res/train.c"
//#include "res/heart.c"
//进入指南针界面
WIN_TrainStruct *TRAIN_EnterCompass (WIN_WindowStruct *base)
{
WIN_WindowStruct *temp=0;
temp=(WIN_WindowStruct *)WIN_CreatTrain ((WIN_WindowStruct *)base,0,0,0,((WIN_WindowStruct *)base)->x_size,((WIN_WindowStruct *)base)->y_size);
WIN_SetBkColor (temp,((WIN_WindowStruct *)base)->bkcolor);
WIN_SetBackPic (temp,&((WIN_WindowStruct *)base)->pic);
((WIN_TrainStruct *)temp)->paint=TRAIN_CompassPaint;
((WIN_TrainStruct *)temp)->title="指南针";
WIN_ShowWindow (temp);
return (WIN_TrainStruct *)temp;
}