一个基于PXA255嵌入式系统的简单24位图片读取输出程序

很简单有兴趣的可以扩展2位,4位,8位,16位读取和图片压缩放大 屏幕为16位TFT-LCE


键盘驱动:key_dd.c

 
#include <linux/module.h>//모듈에 관한 정의 ex)MOD_INC_USE_COUNT
#include <linux/init.h>//init_module() 과 cleanup_module()
#include <linux/delay.h>//udelay()
#include <linux/kernel.h>
#include <asm/uaccess.h>//copy_to_user()
#include <asm/io.h>//GPIO controller에 관한 정의
#include <asm/irq.h>// interrupt에 관한 정의
/* Prototypes */
int key_init (void );
int key_open(struct inode *, struct file *);
int key_release(struct inode *, struct file *);
ssize_t key_read (struct file *inode, char *gdata, size_t length, loff_t *off_what);
ssize_t key_write (struct file *inode, char *gdata, size_t length, loff_t *off_what);
void led_blink(unsigned long i);
void key_handler(int irq, void *dev_id, struct pt_regs *regs);
void clean_module(void);
#define DEVICE_NAME "KEY"
#define KEY_MAJOR   233 //0x00000001로 정의됨
#define KEY_GPIO_0  GPIO_0 // IRQ_GPIO(0)는 0로 정의됨
#define KEY_IRQ     IRQ_GPIO(0)     //key pad data input address
#define KEY_BASE    0x14000000
#define KEY_BYTES   1
#define GPIO_LED_82 0x40000
#define GPIO_LED_83 0x80000
static struct file_operations key_fops =
{
    open:   key_open,
    read:   key_read,
    write: key_write,
    release:key_release,
};
static DECLARE_WAIT_QUEUE_HEAD(wq);
static int Major;
static unsigned long *keyport;
static char key_value;
int key_init(void) {
    int return_val;
    printk("keypad_init n");
    Major = register_chrdev (KEY_MAJOR, DEVICE_NAME, &key_fops);
    if (Major < 0) {
    printk ("KEY init_module: failed with %d n", Major);
        return Major;
    }
    printk ("KEY driver registred: major = %d n", KEY_MAJOR);
    //GPIO 0을 입력으로 설정
    GPDR0 &= ~(GPIO_0);
    //alternate function을 normal GPIO function으로 설정
    GAFR0_L &= ~(0x3);
    //GPIO 0을 falling edge일 때 detect 하도록 설정
    set_GPIO_IRQ_edge( 0, GPIO_FALLING_EDGE);
    //IRQ 요청
       return_val = request_irq(KEY_IRQ, key_handler, SA_INTERRUPT, "KEY PAD INT", NULL );
    if( return_val < 0 ) {
        printk(KERN_ERR "pxa255_pro_key_init() : Can't reqeust irq %#010x n", IRQ_GPIO(0) );
        return -1;
    }
    return 0;
}
/* interrupt service routine */
void key_handler(int irq, void *dev_id, struct pt_regs *regs)
{
    // 키의 물리주소 값을 커널의 임의의 메모리 영역의 주소에 매핑
    keyport = (unsigned long)ioremap(KEY_BASE, 0x10);
    //매핑된 메모리 주소를 이용하여 실제 물리 주소에 있는 값을 가져온다.
    key_value = *(keyport+0) & 0xf;
    printk("KEY INPUT : [0x%x] n",key_value);
    switch(key_value) {
    case 0x3 : printk("u pushed 3rd button. OST will be played.. n"); break;
    case 0xb : printk("u pushed 12th button. Ad will be played.. n"); break;
    default :led_blink(key_value);break;
    }
    //매핑되었던 물리 주소와 메모리 주소를 해제
    iounmap(keyport);
    //block시켜놨던 read() process를 release한다.
    wake_up_interruptible(&wq);
}
ssize_t key_read (struct file *inode, char *gdata, size_t length, loff_t *off_what)
{
    // interrupt가 발생할 때까지 sleep 시킴
    interruptible_sleep_on(&wq);
    printk("value being sent to application : %x n",key_value);
    //application에게 interrupt 번호를 pass한다.
    copy_to_user(gdata, &key_value,sizeof(1));
    return 0;
}
int key_open (struct inode *inode, struct file *file)
{
    printk ("open..ok n");
    printk ("push any key! n");
    //LED D6, D7의 방향을 출력으로 설정한다.
    GPDR2 |= 0xC0000;
    MOD_INC_USE_COUNT;
    return 0;
}
int key_release (struct inode *inode, struct file *file)
{
    printk ("device_release(%p,%p) n", inode, file);
    MOD_DEC_USE_COUNT;
    return 0;
}
ssize_t key_write (struct file *inode, char *gdata, size_t length, loff_t *off_what)
{
    return 0;
}
void led_blink(unsigned long i)
{
    int j=(i & 0xf)+1;
    printk("LED will toggle %x times n", j);
    while(j) {
    GPCR2 |= GPIO_LED_83;//83번을 CLEAR, LED D7 GREEN이 켜짐
    GPSR2 |= GPIO_LED_82;//82번을 SET,     LED D6 RED가 꺼짐
    udelay(90000000000);
    GPCR2 |= GPIO_LED_82;//82번을 CLEAR, LED D6 RED가 켜짐
    GPSR2 |= GPIO_LED_83;//83번을 SET, LED D7 GREEN이 꺼짐
    udelay(90000000000);
    j--;
    }
    GPSR2 |= GPIO_LED_82;//82번을 SET,      LED D6 RED가 꺼짐
    return;
}
module_init(key_init);
module_exit(clean_module);
void clean_module (void)
{
    int ret;
    ret = unregister_chrdev (KEY_MAJOR, DEVICE_NAME);
    if (ret < 0) {
    printk ("unregister_chrdev: error %d n", ret);
    }
    else {
        printk ("module clean up ok!! n");
    }
}
/****************************************************************************/
 
键盘测试程序:app-key-test.c
 
 
#include <stdio.h>
#include <fcntl.h> //open()의 flag 정의되어 있음
#include <errno.h> //errno에 정의 됨
int fd;
int main(int argc, char **argv)
{
    unsigned long status = 0;
    char passed_value;
    if( (fd = open("/dev/KEY", O_RDWR)) < 3) {
    fprintf(stderr, "/dev/int_test device file open error!! .. %s n",strerror(errno));
    close(fd);
    return 0;
}
while(1) {
//커널로부터 넘어온 interrupt 번호를 받는다.
    read(fd, &passed_value,sizeof(1));
    printf("value passed from kernel :%x n", passed_value);
//3번 key를 눌렸을 경우
    if(passed_value==3) {
    system("mixer vol 100");
    system("mixer pcm 100");
    system("madplay /mnt/mtd/sample/sample.mp3");
    }
//12번 key를 눌렸을 경우
    else if(passed_value==0xb) {
    system("mixer vol 100");
    system("mixer pcm 100");
    system("mplayer /mnt/mtd/sample/sample.mpg");
    }
};
close(fd);
return 0;
}
/****************************************************************************/
 
Makefile文件:
 
CC=arm-linux-gcc
INCLUDEDIR = /home/es/Toolchain/linux-2.4.19-pro3_nlcd/include
CFLAGS = -D__KERNEL__ -DMODULE -Wall -O2
CFLAGS2 = -I.. -I$(INCLUDEDIR)
All: key_test_dd test
key_test_dd : key_dd.c
    $(CC) $(CFLAGS) $(CFLAGS2) -c -o key_dd.o key_dd.c
test :app-key-test.c
    $(CC) -o test app-key-test.c
clean :
    rm -rf key_dd.o test
/****************************************************************************/
 
 
程序主文件:
 
#include <math.h>
#include <dirent.h> 
#include <fcntl.h>
#include <string.h>
#include <errno.h> //errno에 정의 됨
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>       /* for exit */
#include <unistd.h> /* for open/close.. */
#include <fcntl.h> /* for O_RDONLY */
#include <sys/ioctl.h> /* for ioctl */
#include <sys/types.h> /* for lseek() */
#include <sys/stat.h>
#include <sys/signal.h>
#include <linux/fb.h> /*for fb_var_screeninfo, FBIOGET_VSCREENINFO*/
#define FBDEVFILE "/dev/fb"
#define WIDTHBYTES(bits) (((bits)+31)/32*4)
 
typedef unsigned char ubyte;
 
unsigned short makepixel(struct fb_var_screeninfo *fbvar, ubyte r, ubyte g, ubyte b)
{
    return (unsigned short)(((r>>3)<<11)|((g>>2)<<5)|(b>>3));
}
typedef struct
{  
    unsigned short  bfType;//表明位图文件的类型,必须为BM
    unsigned long bfSize;//表明位图文件的大小,以字节为单位
    unsigned short  bfReserved1;//属于保留字,必须为本0
    //unsigned short  bfReserved2;//也是保留字,必须为本0
    unsigned long bfOffBits;//位图阵列的起始位置,以字节为单位
} BITMAPFILEHEADER;
 
typedef struct
{
    unsigned long  biSize; //指出本数据结构所需要的字节数
    long  biWidth;//以象素为单位,给出BMP图象的宽度
    long  biHeight;//以象素为单位,给出BMP图象的高度
    unsigned short biPlanes;//输出设备的位平面数,必须置为1
    unsigned short biBitCount;//给出每个象素的位数
    unsigned long  biCompress;//给出位图的压缩类型
    unsigned long  biSizeImage;//给出图象字节数的多少
    long  biXPelsPerMeter;//图像的水平分辨率
    long  biYPelsPerMeter;//图象的垂直分辨率
    unsigned long  biClrUsed;//調色板中图象实际使用的颜色素数
    unsigned long  biClrImportant;//给出重要颜色的索引值
} BITMAPINFOHEADER;
 
typedef struct
{
    //public:
    ubyte     rgbBlue; //该颜色的蓝色分量
    ubyte     rgbGreen; //该颜色的绿色分量
    ubyte     rgbRed; //该颜色的红色分量
    ubyte     rgbReserved; //保留值
} RGBQUAD;
 
 
int bmpload(char* filename)
{
    FILE* fp;
    BITMAPFILEHEADER bmpfile;
    BITMAPINFOHEADER bmpinfo;
    RGBQUAD *dataOfBmp;
    int i, j, k;
    int index = 0;
    long plant;
    int num;
    int bmpwidth;
    int bmpheigh;
    int lwidth;
    ubyte *pColorData;
    long nData;
    int fbfd;
    int ret;
   struct fb_var_screeninfo fbvar;
   unsigned short pixel;
   int offset;
 
    fbfd = open(FBDEVFILE, O_RDWR);
   if(fbfd < 0)
    {
    perror("fbdev open");
      exit(1);
        }
        // 커널로부터 lcd에 관한 정보를 fbvar에 저장한다.
   ret = ioctl(fbfd, FBIOGET_VSCREENINFO, &fbvar);
   if(ret < 0)
    {
    perror("fbdev ioctl");
      exit(1);
        }
 
    if(fbvar.bits_per_pixel!=16)
    {                  //bpp가 16bit인지 check
    fprintf(stderr, "bpp is not 16n");
    exit(1);
    }
     
    fp = fopen(filename, "rb");
    fread(&bmpfile,14L, 1, fp);
    if(bmpfile.bfType != 0x4d42)
        return -1;
    fseek(fp, 14L, 0);
    fread(&bmpinfo,sizeof(BITMAPINFOHEADER), 1, fp);
    bmpwidth = bmpinfo.biWidth;//图片宽度
    bmpheigh = bmpinfo.biHeight;//图片长度
    lwidth = WIDTHBYTES(bmpwidth * bmpinfo.biBitCount);//每行像素大小
 
    pColorData = (ubyte *)malloc(bmpheigh * lwidth);   
    memset(pColorData,0, bmpheigh * lwidth);
    nData = bmpheigh * lwidth;
    dataOfBmp = (RGBQUAD *)malloc(bmpwidth * bmpheigh * sizeof(RGBQUAD));//用于保存各像素对应的RGB数据
    memset(dataOfBmp, 0, bmpwidth * bmpheigh * sizeof(RGBQUAD));
    //把位图数据信息读到数组里   
    fread(pColorData,1,nData,fp); 
    index = 0;
    for(i=0; i < bmpheigh; i++)
        for(j= 0; j < bmpwidth ; j++)
        {
            k = i * lwidth + j*3;
            dataOfBmp[index].rgbRed = pColorData[k+2];   
            dataOfBmp[index].rgbGreen = pColorData[k+1];   
            dataOfBmp[index].rgbBlue = pColorData[k];    
            index++;
        }  
    k = 0;
    for (i = 479; i > -1; i--)
        for (j = 0; j < 640; j++)
        {
            offset = i*fbvar.xres*(16/8)+ j*(16/8);
            if(lseek(fbfd, offset, SEEK_SET) < 0) //file point를 맨 앞에서 offset만큼 옮김
            { 
                perror("fbdev lseek");
            exit(1);
            }
            pixel = makepixel(&fbvar, dataOfBmp[k].rgbRed, dataOfBmp[k].rgbGreen, dataOfBmp[k].rgbBlue);
            write(fbfd, &pixel, 2);
            k += 1;
        }
    fclose(fp);
    free(dataOfBmp);
    free(pColorData);
    return 0;           
}
 
int getkey()
{
    int fd, c, res, i;
    char key;
    fd = open("/dev/KEY", O_RDONLY);
    if(fd < 0)
    {
        perror("/dev/KEY");
        exit(-1);
    }
    else
    {   
        while(key != 0x7)
        {
            printf("Key test startn");
            read(fd, &key, sizeof(1));
            switch(key)
            {
                case 0x0:
                    //printf("Number 3");
                    return 3;
                    break;
                case 0x1:
                    //printf("Number 6");
                    return 6;                   
                    break;
                case 0x2:
                    //printf("Number 9");
                    return 9;
                    break;
                case 0x3:
                    //printf("Number *");
                    return 11;
                    break;
                case 0x4:
                    //printf("Number 2");
                    return 2;
                    break;
                case 0x5:
                    //printf("Number 5");
                    return 5;
                    break;
                case 0x6:
                    //printf("Number 8");
                    return 8;
                    break;
                case 0x7:
                    //printf("Number 0");
                    return 0;
                    break;
                case 0x8:
                    //printf("Number 1");
                    return 1;
                    break;
                case 0x9:
                    //printf("Number 4");
                    return 4;
                    break;
                case 0xa:
                    //printf("Number 7");
                    return 7;
                    break;
 
                case 0xb:
                    //printf("Number #");
                    return 10;
                    break;
            }
        }
    }
    close(fd);
    return 0;
}
 
int load_dd()
{
    int ret;
    ret = system("insmod key_dd.o");
    if (ret == 0)
        ret = system("mknod /dev/KEY c 233 0");
    if (ret != 0)
    {   
 
        printf ("KeyPad fail!");
    }
    return 0;
}
int load_bmp(int key)
{
    char fname[255];
    struct dirent *ptr;   
   DIR *dir;
    dir=opendir("/mnt/usbdisk/");
   while((ptr=readdir(dir))!=NULL)
        {
        //跳过'.'和'..'两个目录
        if(ptr->d_name[0] == '.')
            continue;
        else if(strstr(ptr->d_name,".bmp"))
        {
            printf("%s is ready...n",ptr->d_name);
            sprintf(fname,"/mnt/usbdisk/%s",ptr->d_name);
            bmpload(fname);
            if (key == 1)
            {   
                sleep(4);
            }
            else if (key == 2)
            {   
                sleep(4);
            }
            else
            {   
                key = getkey();
                while (1)
                {   
                    if (key == 5)
                        break;
                    else if (key == 1)
                        break;
                    else if (key == 2)
                        break;                      
                    else if(key == 0)
                    {
                        closedir(dir);
                        return -1;
                    }
                    key = getkey();
                }
            }
        }
        }
    closedir(dir);
    switch (key)
    {
        case 1 :
            return 1;
            break;
        case 2:
            return 2;
            break;
        default :
            return 0;
            break;
    }
}
 
int main()
{
    int ret;
    int key;
     
    load_dd();
     
    key = load_bmp(100);
    while (1)
    {
        if(key == 1)
            key = 100;
        else if(key == -1)
            break;
        key = load_bmp(key);
    }
    exit(0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值