arm 2440 linux 应用程序 nes 红白机模拟器 第4篇 linux 手柄驱动支持
Posted 宁次
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了arm 2440 linux 应用程序 nes 红白机模拟器 第4篇 linux 手柄驱动支持相关的知识,希望对你有一定的参考价值。
小霸王学习机的真实手柄,实测CPU 占用 80%
接线图:
手柄读时序:
joypad.c 驱动: 普通的字符设备驱动。
1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/delay.h> 6 #include <asm/uaccess.h> 7 #include <asm/irq.h> 8 #include <asm/io.h> 9 #include <linux/device.h> 10 11 /** 12 *手柄接线定义 13 *VCC 3.3 来自 串口 14 *GND 来自 串口 15 *CLK 摄像头接口 1P IICSDA GPE15 16 *LATCH 摄像头接口 2P IICSCL GPE14 17 *DAT0 摄像头接口 5P CAMCLK GPJ11 18 */ 19 20 #define GPE_BASE 0x56000040 21 #define GPJ_BASE 0x560000d0 22 23 //定义一个结构体用来保存 GPIO 信息 24 typedef struct { 25 unsigned int con; 26 unsigned int dat; 27 unsigned int up; 28 29 }T_GPIO_REG, *PT_GPIO_REG; 30 31 //禁止编译器优化 32 static volatile PT_GPIO_REG pt_gpe_reg; 33 static volatile PT_GPIO_REG pt_gpj_reg; 34 35 static struct class *joypad_drv_class; 36 37 static ssize_t joypad_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) 38 { 39 //利用 sszie_t 返回 手柄键值 40 //buf 是有符号无法保存 8 bit 41 int i; 42 ssize_t val = 0; 43 pt_gpe_reg->dat |= 1<<14; 44 udelay(2); 45 pt_gpe_reg->dat &= ~(1<<14); 46 for(i=0; i<8; i++) 47 { 48 udelay(2); 49 if(! (pt_gpj_reg->dat & 1<<11)) 50 { 51 val |= 1<<i; 52 } 53 54 pt_gpe_reg->dat |= 1<<15; 55 udelay(2); 56 pt_gpe_reg->dat &= ~(1<<15); 57 } 58 //最后输出低电平 59 pt_gpe_reg->dat &= ~(1<<14 | 1<<15); 60 return val; 61 } 62 63 static struct file_operations joypad_drv_fops = { 64 .owner = THIS_MODULE, 65 .read = joypad_drv_read, 66 }; 67 68 int major; 69 //注册驱动程序 70 int joypad_drv_init(void) 71 { 72 major = register_chrdev(0, "joypad_drv", &joypad_drv_fops); 73 74 //自动创建 dev 节点 75 joypad_drv_class = class_create(THIS_MODULE, "joypad_drv"); 76 device_create(joypad_drv_class, NULL, MKDEV(major, 0), NULL, "joypad"); 77 78 //ioremap 地址映射 79 pt_gpe_reg = ioremap(GPE_BASE, sizeof(T_GPIO_REG)); 80 pt_gpj_reg = ioremap(GPJ_BASE, sizeof(T_GPIO_REG)); 81 82 //配置GPIO 83 //GPE 14 15 配置为输出引脚 84 pt_gpe_reg->con &= ~(3<<(2*15)); 85 pt_gpe_reg->con &= ~(3<<(2*14)); 86 pt_gpe_reg->con |= 1<<(2*15); 87 pt_gpe_reg->con |= 1<<(2*14); 88 89 //默认输出低电平 90 pt_gpe_reg->dat &= ~(1<<14 | 1<<15); 91 92 //GPJ 11 配置为输入引脚 禁用内部上拉 93 pt_gpj_reg->con &= ~(3<<(2*11)); 94 pt_gpj_reg->up |= 1<<11; 95 return 0; 96 } 97 98 //卸载驱动程序 99 void joypad_drv_exit(void) 100 { 101 //取消 地址映射 102 iounmap(pt_gpe_reg); 103 iounmap(pt_gpj_reg); 104 105 unregister_chrdev(major, "joypad_drv"); 106 device_destroy(joypad_drv_class, MKDEV(major, 0)); 107 class_destroy(joypad_drv_class); 108 } 109 110 module_init(joypad_drv_init); 111 module_exit(joypad_drv_exit); 112 MODULE_LICENSE("GPL");
InfoNES InfoNES_System_Linux.cpp:
1 /*===================================================================*/ 2 /* */ 3 /* InfoNES_System_Linux.cpp : Linux specific File */ 4 /* */ 5 /* 2001/05/18 InfoNES Project ( Sound is based on DarcNES ) */ 6 /* */ 7 /*===================================================================*/ 8 9 /*-------------------------------------------------------------------*/ 10 /* Include files */ 11 /*-------------------------------------------------------------------*/ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <pthread.h> 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <fcntl.h> 21 #include <sys/ioctl.h> 22 #include <unistd.h> 23 #include <sys/soundcard.h> 24 25 #include "../InfoNES.h" 26 #include "../InfoNES_System.h" 27 #include "../InfoNES_pAPU.h" 28 29 //bool define 30 #define TRUE 1 31 #define FALSE 0 32 33 /* lcd 操作相关 头文件 */ 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <fcntl.h> 37 #include <linux/fb.h> 38 #include <sys/ioctl.h> 39 #include <unistd.h> 40 #include <string.h> 41 #include <sys/mman.h> 42 #include <termios.h> 43 44 #include <fcntl.h> 45 46 #define JOYPAD_DEV "/dev/joypad" 47 static int joypad_fd; 48 49 static int fb_fd; 50 static unsigned char *fb_mem; 51 static int px_width; 52 static int line_width; 53 static int screen_width; 54 static struct fb_var_screeninfo var; 55 56 static int init_joypad() 57 { 58 joypad_fd = open(JOYPAD_DEV, O_RDONLY); 59 if(-1 == joypad_fd) 60 { 61 printf("joypad dev not found \\r\\n"); 62 return -1; 63 } 64 return 0; 65 } 66 67 static int lcd_fb_display_px(WORD color, int x, int y) 68 { 69 unsigned char *pen8; 70 unsigned short *pen16; 71 72 pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width); 73 pen16 = (unsigned short *)pen8; 74 *pen16 = color; 75 76 return 0; 77 } 78 79 static int lcd_fb_init() 80 { 81 //如果使用 mmap 打开方式 必须是 读定方式 82 fb_fd = open("/dev/fb0", O_RDWR); 83 if(-1 == fb_fd) 84 { 85 printf("cat\'t open /dev/fb0 \\n"); 86 return -1; 87 } 88 //获取屏幕参数 89 if(-1 == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var)) 90 { 91 close(fb_fd); 92 printf("cat\'t ioctl /dev/fb0 \\n"); 93 return -1; 94 } 95 96 //计算参数 97 px_width = var.bits_per_pixel / 8; 98 line_width = var.xres * px_width; 99 screen_width = var.yres * line_width; 100 101 fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0); 102 if(fb_mem == (void *)-1) 103 { 104 close(fb_fd); 105 printf("cat\'t mmap /dev/fb0 \\n"); 106 return -1; 107 } 108 //清屏 109 memset(fb_mem, 0 , screen_width); 110 return 0; 111 } 112 113 /*-------------------------------------------------------------------*/ 114 /* ROM image file information */ 115 /*-------------------------------------------------------------------*/ 116 117 char szRomName[256]; 118 char szSaveName[256]; 119 int nSRAM_SaveFlag; 120 121 /*-------------------------------------------------------------------*/ 122 /* Constants ( Linux specific ) */ 123 /*-------------------------------------------------------------------*/ 124 125 #define VBOX_SIZE 7 126 #define SOUND_DEVICE "/dev/dsp" 127 #define VERSION "InfoNES v0.91J" 128 129 /*-------------------------------------------------------------------*/ 130 /* Global Variables ( Linux specific ) */ 131 /*-------------------------------------------------------------------*/ 132 133 /* Emulation thread */ 134 pthread_t emulation_tid; 135 int bThread; 136 137 /* Pad state */ 138 DWORD dwKeyPad1; 139 DWORD dwKeyPad2; 140 DWORD dwKeySystem; 141 142 /* For Sound Emulation */ 143 BYTE final_wave[2048]; 144 int waveptr; 145 int wavflag; 146 int sound_fd; 147 148 /*-------------------------------------------------------------------*/ 149 /* Function prototypes ( Linux specific ) */ 150 /*-------------------------------------------------------------------*/ 151 152 void *emulation_thread( void *args ); 153 154 155 void start_application( char *filename ); 156 157 158 int LoadSRAM(); 159 160 161 int SaveSRAM(); 162 163 164 /* Palette data */ 165 WORD NesPalette[64] = 166 { 167 0x39ce, 0x1071, 0x0015, 0x2013, 0x440e, 0x5402, 0x5000, 0x3c20, 168 0x20a0, 0x0100, 0x0140, 0x00e2, 0x0ceb, 0x0000, 0x0000, 0x0000, 169 0x5ef7, 0x01dd, 0x10fd, 0x401e, 0x5c17, 0x700b, 0x6ca0, 0x6521, 170 0x45c0, 0x0240, 0x02a0, 0x0247, 0x0211, 0x0000, 0x0000, 0x0000, 171 0x7fff, 0x1eff, 0x2e5f, 0x223f, 0x79ff, 0x7dd6, 0x7dcc, 0x7e67, 172 0x7ae7, 0x4342, 0x2769, 0x2ff3, 0x03bb, 0x0000, 0x0000, 0x0000, 173 0x7fff, 0x579f, 0x635f, 0x6b3f, 0x7f1f, 0x7f1b, 0x7ef6, 0x7f75, 174 0x7f94, 0x73f4, 0x57d7, 0x5bf9, 0x4ffe, 0x0000, 0x0000, 0x0000 175 }; 176 177 /*===================================================================*/ 178 /* */ 179 /* main() : Application main */ 180 /* */ 181 /*===================================================================*/ 182 183 /* Application main */ 184 int main( int argc, char **argv ) 185 { 186 char cmd; 187 188 /*-------------------------------------------------------------------*/ 189 /* Pad Control */ 190 /*-------------------------------------------------------------------*/ 191 192 /* Initialize a pad state */ 193 dwKeyPad1 = 0; 194 dwKeyPad2 = 0; 195 dwKeySystem = 0; 196 197 /*-------------------------------------------------------------------*/ 198 /* Load Cassette & Create Thread */ 199 /*-------------------------------------------------------------------*/ 200 201 /* Initialize thread state */ 202 bThread = FALSE; 203 204 /* If a rom name specified, start it */ 205 if ( argc == 2 ) 206 { 207 start_application( argv[1] ); 208 } 209 210 lcd_fb_init(); 211 init_joypad(); 212 213 //主循环中处理输入事件 214 while(1) 215 { 216 dwKeyPad1 = read(joypad_fd, 0, 0); 217 } 218 return(0); 219 } 220 221 222 /*===================================================================*/ 223 /* */ 224 /* emulation_thread() : Thread Hooking Routine */ 225 /* */ 226 /*===================================================================*/ 227 228 void *emulation_thread( void *args ) 229 { 230 InfoNES_Main(); 231 } 232 233 234 /*===================================================================*/ 235 /* */ 236 /* start_application() : Start NES Hardware */ 237 /* */ 238 /*===================================================================*/ 239 void start_application( char *filename ) 240 { 241 /* Set a ROM image name */ 242 strcpy( szRomName, filename ); 243 244 /* Load cassette */ 245 if ( InfoNES_Load( szRomName ) == 0 ) 246 { 247 /* Load SRAM */ 248 LoadSRAM(); 249 250 /* Create Emulation Thread */ 251 bThread = TRUE; 252 pthread_create( &emulation_tid, NULL, emulation_thread, NULL ); 253 } 254 } 255 256 257 /*===================================================================*/ 258 /* */ 259 /* LoadSRAM() : Load a SRAM */ 260 /* */ 261 /*===================================================================*/ 262 int LoadSRAM() 263 { 264 /* 265 * Load a SRAM 266 * 267 * Return values 268 * 0 : Normally 269 * -1 : SRAM data couldn\'t be read 270 */ 271 272 FILE *fp; 273 unsigned char pSrcBuf[SRAM_SIZE]; 274 unsigned char chData; 275 unsigned char chTag; 276 int nRunLen; 277 int nDecoded; 278 int nDecLen; 279 int nIdx; 280 281 arm linux 应用程序 nes 红白机模拟器 第1篇jz2440: linux/arch/arm/下面的plat-和mach-
S3C2440-裸机篇-02 | 安装和使用arm-linux-gcc交叉编译工具链
[Mini2440 - 008] 安装 arm-linux-gcc 交叉编译器
ubuntu 12.04内核3.2.0-60搭建ARM S3C2440 交叉编译环境要选择哪个版本的ARM-LINUX-GCC啊?谢谢