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-

如何将linux2.6.38内核移植到TQ2440

S3C2440-裸机篇-02 | 安装和使用arm-linux-gcc交叉编译工具链

[Mini2440 - 008] 安装 arm-linux-gcc 交叉编译器

ubuntu 12.04内核3.2.0-60搭建ARM S3C2440 交叉编译环境要选择哪个版本的ARM-LINUX-GCC啊?谢谢