android 开源fc模拟器_战舰开发板触摸屏运行NES模拟器
本帖最后由 xcc521 于 2019-4-3 23:14 編輯
先上圖
ScreenCut003.png (8.39 KB, 下載次數: 0)
2019-4-1 00:58 上傳
ScreenCut004.png (7.29 KB, 下載次數: 0)
2019-4-1 00:58 上傳
使用觸摸屏檢測作為手柄數據輸入
之前還嘗試過NRF24L1無線手柄(見這里 http://www.openedv.com/forum.php?mod=viewthread&tid=278263&extra=)以及自己寫的APP使用藍牙連接
0DCGRV[ES(NX}UG~X7({G3T.png (234.31 KB, 下載次數: 0)
2019-4-1 00:58 上傳
7EMVA`S}BM({FDU9]@GU5}K.png (174.16 KB, 下載次數: 0)
2019-4-1 00:58 上傳
947EE`1VGJ8WWN~H{AWUY.jpg (189.69 KB, 下載次數: 1)
2019-4-1 00:58 上傳
Screenshot_2019-04-01-00-27-43-299_xdtech.joystic.png (82.57 KB, 下載次數: 0)
2019-4-1 00:58 上傳
Screenshot_2019-04-01-00-27-49-053_xdtech.joystic.png (146.82 KB, 下載次數: 0)
2019-4-1 00:58 上傳
Screenshot_2019-04-01-00-28-00-980_com.android.se.png (82.67 KB, 下載次數: 0)
2019-4-1 00:58 上傳
Screenshot_2019-04-01-00-28-25-494_xdtech.joystic.png (91.93 KB, 下載次數: 0)
2019-4-1 00:58 上傳
Screenshot_2019-04-01-00-28-36-472_xdtech.joystic.png (158.93 KB, 下載次數: 0)
2019-4-1 00:58 上傳
藍牙模塊連接串口3,安卓APP發送字符表示按鍵
//讀取游戲手柄數據
void nes_get_gamepadval(void)
{
if(USART3_RX_STA & 0x08000)
{
//printf("usart3 data:%s\r\n",USART3_RX_BUF);
if(USART3_RX_BUF[0] == 'A')
{
PADdata0 |= 0x10;
}
else
{
PADdata0 &= ~0x10;
}
if(USART3_RX_BUF[1] == 'B')
{
PADdata0 |= 0x20;
}
else
{
PADdata0 &= ~0x20;
}
if(USART3_RX_BUF[2] == 'C')
{
PADdata0 |= 0x40;
}
else
{
PADdata0 &= ~0x40;
}
if(USART3_RX_BUF[3] == 'D')
{
PADdata0 |= 0x80;
}
else
{
PADdata0 &= ~0x80;
}
if(USART3_RX_BUF[4] == 'E')
{
PADdata0 |= 0x01;
}
else
{
PADdata0 &= ~0x01;
}
if(USART3_RX_BUF[5] == 'F')
{
PADdata0 |= 0x02;
}
else
{
PADdata0 &= ~0x02;
}
if(USART3_RX_BUF[6] == 'G')
{
PADdata0 |= 0x04;
}
else
{
PADdata0 &= ~0x04;
}
if(USART3_RX_BUF[7] == 'H')
{
PADdata0 |= 0x08;
}
else
{
PADdata0 &= ~0x08;
}
USART3_RX_STA = 0;
}
//PADdata0=JOYPAD_Read();? ?? ???//讀取手柄1的值
//PADdata1=0;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???//沒有手柄2,故不采用.
}
注意運行NES的時候倍頻需要修改串口3的設置
void usart3_fast_init(u32 pclk2,u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
float temp;
u16 mantissa;
u16 fraction;
temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
mantissa=temp;? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?//得到整數部分
fraction=(temp-mantissa)*16; //得到小數部分
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<3;? ?? ?? ???//使能PORTB口時鐘
GPIOB->CRH&=0XFFFF00FF;? ?? ???//IO狀態設置
GPIOB->CRH|=0X00008B00;? ?? ???//IO狀態設置
RCC->APB1ENR|=1<<18;? ?? ?? ? //使能串口時鐘
RCC->APB1RSTR|=1<<18;? ?//復位串口3
RCC->APB1RSTR&=~(1<<18);//停止復位
//波特率設置
USART3->BRR=mantissa; // 波特率設置
USART3->CR1|=0X200C;??//1位停止,無校驗位.
#if EN_USART1_RX? ?? ?? ?? ?? ?? ?//如果使能了接收
//使能接收中斷
USART3->CR1|=1<<5;? ?? ?? ?? ?//接收緩沖區非空中斷使能2
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//搶占優先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;? ?? ?? ?? ?? ? //子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;? ?? ?? ?? ?? ?? ?? ?? ?//IRQ通道使能
NVIC_Init(&NVIC_InitStructure);? ?? ???//根據指定的參數初始化VIC寄存器
#endif
TIM7_Int_Init(99,7199);? ?? ?? ?? ?? ? //10ms中斷
USART3_RX_STA=0;? ?? ?? ?? ?? ? //清零
TIM_Cmd(TIM7,DISABLE);? ?? ?? ?? ?? ?? ?? ?? ?//關閉定時器7
}
安卓負責連接藍牙監聽按鈕狀態
class mImageListenter implements View.OnTouchListener
{
@Override
public boolean onTouch(View view,MotionEvent motionEvent)
{
// TODO Auto-generated method stub
switch (motionEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (view.getId() == R.id.im_joy_a_mode)
{
send_data[4] = 'E';
}
if (view.getId() == R.id.im_joy_b)
{
send_data[1] = 'B';
}
if (view.getId() == R.id.im_joy_b_mode)
{
send_data[5] = 'F';
}
if (view.getId() == R.id.im_joy_f)
{
send_data[0] = 'A';
}
if (view.getId() == R.id.im_joy_l)
{
send_data[2] = 'C';
}
if (view.getId() == R.id.im_joy_r)
{
send_data[3] = 'D';
}
if (view.getId() == R.id.im_joy_sel)
{
send_data[6] = 'G';
}
if (view.getId() == R.id.im_joy_sta)
{
send_data[7] = 'H';
}
break;
case MotionEvent.ACTION_UP:
if (view.getId() == R.id.im_joy_a_mode)
{
send_data[4] = '0';
}
if (view.getId() == R.id.im_joy_b)
{
send_data[1] = '0';
}
if (view.getId() == R.id.im_joy_b_mode)
{
send_data[5] = '0';
}
if (view.getId() == R.id.im_joy_f)
{
send_data[0] = '0';
}
if (view.getId() == R.id.im_joy_l)
{
send_data[2] = '0';
}
if (view.getId() == R.id.im_joy_r)
{
send_data[3] = '0';
}
if (view.getId() == R.id.im_joy_sel)
{
send_data[6] = '0';
}
if (view.getId() == R.id.im_joy_sta)
{
send_data[7] = '0';
}
break;
default:
break;
}
return true;
}
}
如此就可以控制NES游戲了
轉回主題,使用觸摸屏控制
首先創建界面
_btn_obj * tbtn_game[8];? ?? ?? ?? ?? ? //總共8個按鈕
void load_ctr_ui(void)
{
u16 button_w,button_h,W,H;
uint8_t rval=0;
uint8_t i;
if(lcddev.width == 480)
{
button_w = 60;
button_h = 40;
}
else
{
button_w = 30;
button_h = 18;
}
W = (lcddev.width - button_w * 6) / (6 + 1);//計算縫隙寬度
H = (lcddev.height??- 552 - button_h * 3) / (3 + 1);//計算縫隙高度
tbtn_game[0]=btn_creat(button_w * 1 + W * 2, 552 + button_h * 0 + H * 1,button_w,button_h,0,0x02);? ?? ???//創建按鈕
tbtn_game[1]=btn_creat(button_w * 1 + W * 2, 552 + button_h * 2 + H * 3,button_w,button_h,1,0x02);? ?? ???//創建按鈕
tbtn_game[2]=btn_creat(button_w * 0 + W * 1, 552 + button_h * 1 + H * 2,button_w,button_h,2,0x02);? ?? ???//創建按鈕
tbtn_game[3]=btn_creat(button_w * 2 + W * 3, 552 + button_h * 1 + H * 2,button_w,button_h,3,0x02);? ?? ???//創建按鈕
tbtn_game[4]=btn_creat(button_w * 4 + W * 5, 552 + button_h * 0 + H * 1,button_w,button_h,4,0x02);? ?? ???//創建按鈕
tbtn_game[5]=btn_creat(button_w * 4 + W * 5, 552 + button_h * 2 + H * 3,button_w,button_h,5,0x02);? ?? ???//創建按鈕
tbtn_game[6]=btn_creat(button_w * 3 + W * 4, 552 + button_h * 1 + H * 2,button_w,button_h,6,0x02);? ?? ???//創建按鈕
tbtn_game[7]=btn_creat(button_w * 5 + W * 6, 552 + button_h * 1 + H * 2,button_w,button_h,7,0x02);? ?? ???//創建按鈕
for(i=0;i<8;i++)
{
if(tbtn_game==NULL)
{
rval=1;
break;
}
tbtn_game->bcfucolor=BLACK;//松開時為黑色
tbtn_game->bcfdcolor=WHITE;//按下時為白色
tbtn_game->bkctbl[0]=0X453A;//邊框顏色
tbtn_game->bkctbl[1]=0X5DDC;//第一行的顏色
tbtn_game->bkctbl[2]=0X5DDC;//上半部分顏色
tbtn_game->bkctbl[3]=0X453A;//下半部分顏色
if(i==0)tbtn_game->caption="Select";
if(i==1)tbtn_game->caption="Start";
if(i==2)tbtn_game->caption="Left";
if(i==3)tbtn_game->caption="Right";
if(i==4)tbtn_game->caption="Up";
if(i==5)tbtn_game->caption="Down";
if(i==6)tbtn_game->caption="A";
if(i==7)tbtn_game->caption="B";
}
if(rval==0)//無錯誤
{
for(i=0;i<8;i++)btn_draw(tbtn_game);? ?? ???//畫按鈕
}
}
創建就有刪除,所以
void delete_ctr_ui(void)
{
uint8_t i;
for(i=0;i<8;i++)
btn_delete(tbtn_game);//刪除按鈕
}
然后是檢測按鍵邏輯
uint8_t get_ctr_res(void)
{
uint8_t res = 0,i,val = 0;
tp_dev.scan(0);
in_obj.get_key(&tp_dev,IN_TYPE_TOUCH);? ?? ???//得到按鍵鍵值
for(i=0;i<8;i++)
{
res=game_btn_check(tbtn_game,&in_obj);//確認按鈕檢測
if(res)
{
if((tbtn_game->sta&0X80)==0)//有有效操作
{
switch(i)
{
case 0:
val |= 1 << 2;
break;
case 1:
val |= 1 << 3;
break;
case 2:
val |= 1 << 6;
break;
case 3:
val |= 1 << 7;
break;
case 4:
val |= 1 << 4;
break;
case 5:
val |= 1 << 5;
break;
case 6:
val |= 1 << 0;
break;
case 7:
val |= 1 << 1;
break;
}
}
}
}
return val;
}
game_btn_check本來用的是之前的btn_check,但是不支持實時監測,于是修改成了
static uint8_t game_btn_check(_btn_obj * btnx,void * in_key)
{
_in_obj *key=(_in_obj*)in_key;
uint8_t btnok=0;
if((btnx->sta&0X03)==BTN_INACTIVE)return 0;//無效狀態的按鍵,直接不檢測
switch(key->intype)
{
case IN_TYPE_TOUCH:? ?? ???//觸摸屏按下了
if(btnx->topy&&key->ytop+btnx->height)&&btnx->leftx&&key->xleft+btnx->width))//在按鍵內部
{
btnx->sta&=~(0X03);
btnx->sta|=BTN_PRESS;//按下
//btn_draw(btnx);//畫按鈕??屏蔽重繪按鈕,嚴重影響幀數
btnok=1;
}else
{
btnx->sta&=~(0X03);
btnx->sta|=BTN_RELEASE;? ?? ???//松開
//btn_draw(btnx);? ?? ?? ?? ?? ?? ?? ?? ?//畫按鈕
}
break;
default:
break;
}
return btnok;
}
主循環
LCD_Set_Window(0,0,lcddev.width,lcddev.height);//恢復屏幕窗口用于更新屏幕按鍵狀態以及顯示文字
nes_get_gamepadval();? ?? ???//每3幀查詢一次USB
nes_set_window();//因為檢測屏幕按鍵時候更新了按鈕狀態所以需要重新設置窗口
apu_soundoutput();? ?? ?? ?? ?? ? //輸出游戲聲音
這樣折騰了一晚上就可以按觸摸屏一直輸出按鈕值,不然的話每一次查詢按鍵都要手動點一次放開根本跟不上
但是又發現了個問題,就是按鈕值無法組合,也就是只能檢測任一個按鍵,不能多按鍵同時檢測,本來以為就是其中的8個按鈕都單獨調用一次掃描觸屏函數就會好,但是一想每次檢測的應該還是第一個按下的坐標,這可能就得需要掃描多點觸摸時的坐標了,嗯,暫時就是這樣想的,后面再從底層重寫掃描函數吧,快一點了,睡覺,哈哈哈
藍牙手柄APP.zip
(1.84 MB, 下載次數: 10)
2019-4-1 00:58 上傳
點擊文件名下載附件
IMG_20190401_000056.jpg (2.83 MB, 下載次數: 0)
2019-4-3 23:13 上傳
IMG_20190401_000125.jpg (2.93 MB, 下載次數: 0)
2019-4-3 23:14 上傳
好奇怪附件會亂
總結
以上是生活随笔為你收集整理的android 开源fc模拟器_战舰开发板触摸屏运行NES模拟器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件下载网址大全
- 下一篇: 罗斯蒙特流量计工作原理