基于linux的OLED移植过程

作者:余黔江

 

硬件平台:S3C6410

软件环境:Linux2.3.6

文件系统:android2.3

 

一、移植前准备工作

1.      熟悉s3c6410的SPI驱动工作流程

2.      将s3c6410 SPI的TX与RX连接到一起,测试SPI是否正常

3.      在SPI正常的前提下,仔细阅读ssd1353芯片手册,尤其是上电时序部分

 

二、开始移植SPI总线驱动

1.      在mach-s3c64xx/mach-xxx6410.c中添加如下部分(我用的是SPI0,6410有两个SPI)

s3c64xx_spi_set_info(0,0,2);

spi_register_board_info(s3c6410_spi0_board,ARRAY_SIZE(s3c6410_spi0_board));

 

1.1.       s3c64xx_spi_set_info(0,0,2);

该函数定义在dev-spi.c中

void __init s3c64xx_spi_set_info(int cntrlr, intsrc_clk_nr, int num_cs)

{

  structs3c64xx_spi_info *pd;

 

  /* Reject invalidconfiguration */

  if (!num_cs ||src_clk_nr < 0

                ||src_clk_nr > S3C64XX_SPI_SRCCLK_48M) {

         printk(KERN_ERR"%s: Invalid SPI configuration\n", __func__);

         return;

  }

 

  switch (cntrlr) {

  case 0:

         pd = &s3c64xx_spi0_pdata;

         break;

  case 1:

         pd =&s3c64xx_spi1_pdata;

         break;

  default:

         printk(KERN_ERR"%s: Invalid SPI controller(%d)\n",

                                            __func__,cntrlr);

         return;

  }

 

  pd->num_cs =num_cs;

  pd->src_clk_nr= src_clk_nr;

  pd->src_clk_name= spi_src_clks[src_clk_nr];

}

 

其中static structs3c64xx_spi_info s3c64xx_spi0_pdata = {

  .cfg_gpio =s3c64xx_spi_cfg_gpio,

  .fifo_lvl_mask =0x7f,

  .rx_lvl_offset =13,

};

 

static int s3c64xx_spi_cfg_gpio(struct platform_device*pdev)

{//此函数初始化SPI相关管脚

  switch(pdev->id) {

  case 0:

         s3c_gpio_cfgpin(S3C64XX_GPC(0),S3C64XX_GPC0_SPI_MISO0);

         s3c_gpio_cfgpin(S3C64XX_GPC(1),S3C64XX_GPC1_SPI_CLKO);

         s3c_gpio_cfgpin(S3C64XX_GPC(2),S3C64XX_GPC2_SPI_MOSIO);

         s3c_gpio_setpull(S3C64XX_GPC(0),S3C_GPIO_PULL_UP);

         s3c_gpio_setpull(S3C64XX_GPC(1),S3C_GPIO_PULL_UP);

         s3c_gpio_setpull(S3C64XX_GPC(2),S3C_GPIO_PULL_UP);

         break;

 

  case 1:

         s3c_gpio_cfgpin(S3C64XX_GPC(4),S3C64XX_GPC4_SPI_MISO1);

         s3c_gpio_cfgpin(S3C64XX_GPC(5),S3C64XX_GPC5_SPI_CLK1);

         s3c_gpio_cfgpin(S3C64XX_GPC(6),S3C64XX_GPC6_SPI_MOSI1);

         s3c_gpio_setpull(S3C64XX_GPC(4),S3C_GPIO_PULL_UP);

         s3c_gpio_setpull(S3C64XX_GPC(5),S3C_GPIO_PULL_UP);

         s3c_gpio_setpull(S3C64XX_GPC(6),S3C_GPIO_PULL_UP);

         break;

 

  default:

         dev_err(&pdev->dev,"Invalid SPI Controller number!");

         return-EINVAL;

  }

 

  return 0;

}

1.2.       spi_register_board_info(s3c6410_spi0_board,ARRAY_SIZE(s3c6410_spi0_board));

s3c6410_spi0_board----->

static structspi_board_info s3c6410_spi0_board[] = {

    [0] = {

        .modalias = "spidev",

        .bus_num= 0,

        .chip_select= 0,

        .irq =IRQ_SPI0,

        .max_speed_hz= 1000000, //500*1000,

        .mode=SPI_MODE_2,/* CPOL=1, CPHA=0 */

        .controller_data=&s3c64xx_spi0_csinfo,

    },

};

 

 

s3c64xx_spi0_csinfo----->

static voidcs_set_level(unsigned line_id, int lvl) {

    gpio_direction_output(line_id, lvl);

}

 

static structs3c64xx_spi_csinfo s3c64xx_spi0_csinfo = {

    .fb_delay=100,

    .line=S3C64XX_GPC(3),

    .set_level=cs_set_level,

};

      

              spi_register_board_info----->drivers/spi/spi.c中,将spi添加进入到链表中

              int __init

spi_register_board_info(struct spi_board_infoconst *info, unsigned n)

{

    structboardinfo      *bi;

 

    bi =kmalloc(sizeof(*bi) + n * sizeof*info, GFP_KERNEL);//注意观察此处分配大小的奥妙,牛人就是牛人,佩服!

    if (!bi)

           return-ENOMEM;

    bi->n_board_info= n;

    memcpy(bi->board_info,info, n * sizeof *info);

 

    mutex_lock(&board_lock);

    list_add_tail(&bi->list,&board_list);

    mutex_unlock(&board_lock);

    return0;

}

 

 

2.             platform_add_devices(xxx6410_devices, ARRAY_SIZE(xxx6410_devices));中添加设备驱动

2.1. xxx6410_devices ----->

添加 &s3c64xx_device_spi0,

2.1.1 s3c64xx_device_spi0,------>

       定义在dev-spi.c中

       structplatform_device s3c64xx_device_spi0 = {

       .name              = "s3c64xx-spi",

       .id           = 0,

       .num_resources        =ARRAY_SIZE(s3c64xx_spi0_resource),

       .resource   =s3c64xx_spi0_resource,

       .dev= {

              .dma_mask            = &spi_dmamask,

              .coherent_dma_mask     = DMA_BIT_MASK(32),

              .platform_data= &s3c64xx_spi0_pdata,

       },

};

 

static struct resource s3c64xx_spi0_resource[] = {

       [0]= {

              .start= S3C64XX_PA_SPI0,

              .end   = S3C64XX_PA_SPI0 + 0x100 - 1,

              .flags= IORESOURCE_MEM,

       },

       [1]= {

              .start= DMACH_SPI0_TX,

              .end   = DMACH_SPI0_TX,

              .flags= IORESOURCE_DMA,

       },

       [2]= {

              .start= DMACH_SPI0_RX,

              .end   = DMACH_SPI0_RX,

              .flags= IORESOURCE_DMA,

       },

       [3]= {

              .start= IRQ_SPI0,

              .end   = IRQ_SPI0,

              .flags= IORESOURCE_IRQ,

       },

};

 

-------> static struct s3c64xx_spi_info s3c64xx_spi0_pdata = {

       .cfg_gpio =s3c64xx_spi_cfg_gpio,

       .fifo_lvl_mask = 0x7f,

       .rx_lvl_offset = 13,

};

 

 

 

3.             spi总线注册以及spi_master的注册 drivers/spi/spi.c

4.             s3c6410平台驱动注册drivers/spi/spi_s3c64xx.c

5.             设备驱动注册drivers/spi/spidev.c此部分是重点说明的部分

static int __init spidev_init(void)

{

     int status;

 

     /* Claim our256 reserved device numbers.  Thenregister a class

      * that will key udev/mdev to add/remove /devnodes.  Last, register

      * the driver which manages those devicenumbers.

      */

     BUILD_BUG_ON(N_SPI_MINORS> 256);

     status =register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);

     if (status <0)

            returnstatus;

 

     spidev_class = class_create(THIS_MODULE, "spidev");

     if(IS_ERR(spidev_class)) {

            unregister_chrdev(SPIDEV_MAJOR,spidev_spi_driver.driver.name);

            returnPTR_ERR(spidev_class);

     }

 

     status = spi_register_driver(&spidev_spi_driver);

     if (status <0) {

            class_destroy(spidev_class);

            unregister_chrdev(SPIDEV_MAJOR,spidev_spi_driver.driver.name);

     }

     return status;

}

module_init(spidev_init);

 

spidev_spi_driver------------------->

static structspi_driver spidev_spi_driver = {

     .driver = {

            .name =          "spidev",

            .owner = THIS_MODULE,

     },

     .probe =  spidev_probe,

     .remove =       __devexit_p(spidev_remove),

      */

};

 

 

 

static int__devinit spidev_probe(struct spi_device *spi)

{

     struct spidev_data   *spidev;

     int                 status,err;

     unsigned long        minor;

 

     /* Allocate driver data */

     spidev = kzalloc(sizeof(*spidev), GFP_KERNEL);//分配spidev数据空间

     if (!spidev)

            return -ENOMEM;

 

     /* Initialize the driver data */

     spidev->spi = spi;

     spin_lock_init(&spidev->spi_lock);

     mutex_init(&spidev->buf_lock);

 

     INIT_LIST_HEAD(&spidev->device_entry);

 

     /* If we can allocate a minor number, hookup this device.

      *Reusing minors is fine so long as udev or mdev is working.

      */

     mutex_lock(&device_list_lock);

     minor = find_first_zero_bit(minors,N_SPI_MINORS);

     if (minor < N_SPI_MINORS) {

            struct device *dev;

 

            spidev->devt = MKDEV(SPIDEV_MAJOR,minor);

            dev =device_create(spidev_class, &spi->dev, spidev->devt,

                              spidev, "spidev%d.%d",

                              spi->master->bus_num,spi->chip_select);

//此处创建设备文件/dev/spidev0.0等文件

            status = IS_ERR(dev) ? PTR_ERR(dev): 0;

 

            //sysfs_create_group(&dev->kobj,&attr_group);

     } else {

            dev_dbg(&spi->dev, "nominor number available!\n");

            status = -ENODEV;

     }

     if (status == 0) {

            set_bit(minor, minors);

            list_add(&spidev->device_entry,&device_list);

     }

     mutex_unlock(&device_list_lock);

 

     if (status == 0)

            spi_set_drvdata(spi, spidev);

     else

            kfree(spidev);

    

      //writel(readl(S3C64XX_GPQCON) |S3C64XX_GPQ1_EINT_G9_1, S3C64XX_GPQCON);    

     //err = request_irq(188,FR_synchronization_irq_hander, IRQF_ONESHOT ,

      //                    "oled_fr_sync",NULL);

     //if (err < 0)

     //     printk("\n***********registerfr sync irq failed.\n");

 

     oled_gpio_init(); //此处对SSD1353控制管脚进行初始化

      

     return status;

}

 

 

spidev_fops -------->

static conststruct file_operations spidev_fops = {

     .owner = THIS_MODULE,

     /* REVISIT switch to aio primitives, sothat userspace

      *gets more complete API coverage.  It'llsimplify things

      *too, except for the locking.

      */

     .write =   spidev_write,

     .read =           spidev_read,

     .unlocked_ioctl = spidev_ioctl,

     .open =          spidev_open,

     .release = spidev_release,

};

 

static int spidev_open(struct inode*inode, struct file *filp)

{

     struct spidev_data   *spidev;

     int                 status= -ENXIO;

 

     mutex_lock(&device_list_lock);

 

     list_for_each_entry(spidev,&device_list, device_entry) {

            if (spidev->devt ==inode->i_rdev) {

                   status = 0;

                   break;

            }

     }

     if (status == 0) {

            if (!spidev->buffer) {

                   spidev->buffer= kmalloc(bufsiz, GFP_KERNEL);此处分配ram的缓冲区,故每次发送数据最大只能发送4096 byte

                   if (!spidev->buffer) {

                          dev_dbg(&spidev->spi->dev,"open/ENOMEM\n");

                          status = -ENOMEM;

                   }

            }

            if (status == 0) {

                   spidev->users++;

                   filp->private_data =spidev;

                   nonseekable_open(inode,filp);

            }

     } else

            pr_debug("spidev: nothing forminor %d\n", iminor(inode));

 

     mutex_unlock(&device_list_lock);

     return status;

}

spidev_ioctl --------->

static long

spidev_ioctl(structfile *filp, unsigned int cmd, unsigned long arg)

{

     。。。。。。

 

     switch (cmd) {

     /* read requests */

     case SPI_IOC_RD_MODE:

            retval = __put_user(spi->mode& SPI_MODE_MASK,

                                 (__u8 __user*)arg);

            break;

     case SPI_IOC_RD_LSB_FIRST:

            retval = __put_user((spi->mode& SPI_LSB_FIRST) ?  1 : 0,

                                 (__u8 __user*)arg);

            break;

     case SPI_IOC_RD_BITS_PER_WORD:

            retval =__put_user(spi->bits_per_word, (__u8 __user *)arg);

            break;

     case SPI_IOC_RD_MAX_SPEED_HZ:

            retval =__put_user(spi->max_speed_hz, (__u32 __user *)arg);

            break;

 

     /* write requests */

     case SPI_IOC_WR_MODE:

            retval = __get_user(tmp, (u8 __user*)arg);

            if (retval == 0) {

                   u8    save = spi->mode;

 

                   if (tmp & ~SPI_MODE_MASK){

                          retval = -EINVAL;

                          break;

                   }

 

                   tmp |= spi->mode &~SPI_MODE_MASK;

                   spi->mode = (u8)tmp;

                   retval = spi_setup(spi);

                   if (retval < 0)

                          spi->mode = save;

                   else

                          dev_dbg(&spi->dev,"spi mode %02x\n", tmp);

            }

            break;

     case SPI_IOC_WR_LSB_FIRST:

            retval = __get_user(tmp, (__u8__user *)arg);

            if (retval == 0) {

                   u8    save = spi->mode;

 

                   if (tmp)

                          spi->mode |=SPI_LSB_FIRST;

                   else

                          spi->mode &=~SPI_LSB_FIRST;

                   retval = spi_setup(spi);

                   if (retval < 0)

                          spi->mode = save;

                   else

                          dev_dbg(&spi->dev,"%csb first\n",

                                        tmp ?'l' : 'm');

            }

            break;

     case SPI_IOC_WR_BITS_PER_WORD:

            retval = __get_user(tmp, (__u8__user *)arg);

            if (retval == 0) {

                   u8    save = spi->bits_per_word;

 

                   spi->bits_per_word = tmp;

                   retval = spi_setup(spi);

                   if (retval < 0)

                          spi->bits_per_word= save;

                   else

                          dev_dbg(&spi->dev,"%d bits per word\n", tmp);

            }

            break;

     case SPI_IOC_WR_MAX_SPEED_HZ:

            retval = __get_user(tmp, (__u32__user *)arg);

            if (retval == 0) {

                   u32  save = spi->max_speed_hz;

 

                   spi->max_speed_hz = tmp;

                   retval = spi_setup(spi);

                   if (retval < 0)

                          spi->max_speed_hz =save;

                   else

                          dev_dbg(&spi->dev,"%d Hz (max)\n", tmp);

            }

            break;

     case SPI_IOC_OLED_INIT:

            SSD1353_initial(spidev);

            retval = 0;

            break;

     case SPI_IOC_SET_CURSOR:

            ioc = (struct spi_ioc_transfer*)arg;

            OLED_SetCursor(spidev,ioc->XSpos, ioc->XCpos, ioc->YSpos, ioc->YCpos);

            retval = 0;

            break;

     case SPI_IOC_SET_FONT:

            ioc = (struct spi_ioc_transfer*)arg;

            FrontSetup(ioc);

            break;

     case SPI_IOC_CLEAR_SCREEN:

            ioc = (struct spi_ioc_transfer*)arg;

            OLED_ClearScreen(spidev,ioc->Color);

            break;

     case SPI_IOC_SCREEN_SLEEP:

            ioc = (struct spi_ioc_transfer*)arg;

            OLED_Sleep(spidev,ioc->Status);

            break;

     case SPI_IOC_SEND_STRING:

            ioc = (struct spi_ioc_transfer*)arg;

            OLED_ClearScreen(spidev,ioc->Color);

            OLED_DisplayChar(spidev,15, 40, 0);

            break;

     default:

 

     }

}

 

static voidSSD1353_initial(struct spidev_data  *spidev)

{  

     u8 data[2];

    

 

     LCD_RS(1);   //DC  1:data 0:command    //DC = 1 

     LCD_RS(1);         

     LCD_RESET(1); //RESB 0:reset 1:normal         

     LCD_RESET(0);   

     mdelay(5);     

     LCD_RESET(1);   

     mdelay(100);        

     //comm_out8(spidev,  0xae); Display off      

     //comm_out8(spidev, 0xa8); //Set MUX ratio

     data[0] = 0xae; data[1] = 0xa8;

     oled_WriteLongCmd(spidev, data, 2);

     data_out8(spidev, 0x7f);

    

     comm_out8(spidev, 0xa1); //Display start line    

     data_out8(spidev, 0x00);      

    

     comm_out8(spidev, 0xa2); //Set displayoffset    

     data_out8(spidev, 0x00);      

    

     comm_out8(spidev, 0xa4); //Normal display

     comm_out8(spidev, 0xa0); //Set re-map      

     data_out8(spidev, 0x66); //65K Color

    

     comm_out8(spidev, 0x87); //Master currentcontrol    

     data_out8(spidev, 0x0f);

    

     comm_out8(spidev, 0x81); //Set contrastlevel for R  

     data_out8(spidev, 0x75); //Red contrast set  

    

     comm_out8(spidev, 0x82); //Set contrastlevel for G  

     data_out8(spidev, 0x60); //Green contrastset      

    

     comm_out8(spidev, 0x83); //Set contrastlevel for B

     data_out8(spidev, 0x6a); //Blue contrastset 

    

     comm_out8(spidev, 0xb1); //Phase adjust    

     data_out8(spidev, 0x22);      

    

     comm_out8(spidev, 0xb3); //Set frame rate 

     data_out8(spidev, 0x40);      

    

     comm_out8(spidev, 0xbb); //Set Pre-chargelevel

     data_out8(spidev, 0x08);      

    

     comm_out8(spidev, 0xbe); //VCOMH setting     

     data_out8(spidev, 0x2f);

    

     comm_out8(spidev, 0xb9);   

     cleanDDR(spidev); //Clear the whole DDRAM   

     comm_out8(spidev, 0xaf); //Display on

}

 

/******************************************************************************* 

* FunctionName  : OLED_SetCursor 

*Description    : Sets the cursorposition. 

* Input          : - Xpos: specifies the Xposition. 

*                  - Ypos: specifies the Yposition. 

* Output         : None 

* Return         : None 

*******************************************************************************/  

 void OLED_SetCursor(struct spidev_data*spidev, u8 XSpos,u8 XCpos, u8 YSpos,u8 YCpos)        //S: start C: close  

{     

  comm_out8(spidev,  0x15); // Set Column Address   

  data_out8(spidev,  XSpos);                  

  data_out8(spidev,  XCpos);  

  comm_out8(spidev,  0x75);  // Set Row Address  

  data_out8(spidev,  YSpos);               

  data_out8(spidev,  YCpos);                                  

}  

 

/******************************************************************************* 

* FunctionName  : FrontSetup 

*Description    : Setup a Front LIB onOLED. 

* Input          : - FontID: This parameter can be one of thefollowing values: 

*                    : 

* Output         : None 

* Return         : None 

*******************************************************************************/  

 void FrontSetup(struct spi_ioc_transfer *ioc)

    

        CurrentENFront = ioc->Charfont;  

     Words = ioc->Words;

     CharWidth = ioc->CharWidth;

     CharHeight = ioc->CharHeight;

     BackColor = ioc->BackColor;

     TextColor = ioc->TextColor;

     CharSize = ioc->CharSize;

 

     //printk("font[38] = %x, Words :%d,CharWidth:%d, CharHeight:%d, BackColor:%x, TextColor:%x, CharSize:%d\n)",CurrentENFront[38], Words, CharWidth, CharHeight, BackColor, TextColor,CharSize);

}

 

voidOLED_DisplayChar(struct spidev_data *spidev, u8 Column,u8 Row,u8 Ascii)   

{      

     u16 MapAddress =0;  

  

     Ascii -= 0x20;  

     //CharHeight = CurrentENFront[7];  

     //CharWidth  = CurrentENFront[Ascii*4+9];  

     //MapAddress =CurrentENFront[Ascii*4+10]+CurrentENFront[Ascii*4+11]*256;   

     for (MapAddress = 0; MapAddress <Words; MapAddress++) //4 // 4 represents the number of words

     OLED_DrawChar(spidev, Column + MapAddress* (CharWidth + 1),Row, CurrentENFront+ MapAddress *CharSize);   

//OLED_DrawChar(spidev, Column,Row,&CurrentENFront[MapAddress]);

     //Xcursor =    Column + CharWidth;  

     //Ycursor =  Row;  

}  

 

 

 

voidOLED_DrawChar(struct spidev_data *spidev, u8 Xpos, u8 Ypos, u8 *buffer)  

{  

        u8index = 0;  

        u8i = 0,j = 0;  

       u8  multiple = 0; 

        u8*buf;

        int  size;

       u16  k = 0;

 

           

      OLED_SetCursor(spidev,Xpos,Xpos+CharWidth-1,Ypos,Ypos+CharHeight-1);  

      OLED_WriteRAMPrepare(spidev);  

      multiple = (CharWidth-1)/8+1;  

 

     size = 2 * CharHeight * ((multiple-1) * 8 +(CharWidth -(multiple -1)*8));

     printk("\n*** size = %d\n",size);

     buf = (u8 *)kcalloc(size+1, sizeof(u8),GFP_KERNEL);

    

      for(index = 0; index < CharHeight; index++)  

      {  

               for(j=0;j<(multiple-1);j++)  {

                         for(i=0; i<8; i++)  

                         {  

                                  if((buffer[index*multiple+j]&(0x80>>i))== 0x00)  

                                  {  

                                    //OLED_WriteRAM(spidev,BackColor); 

                                          buf[k] = (u8)(BackColor >> 8);

                                          buf[k+1] = (u8)BackColor &0x0f;

                                  }  

                                  else  

                                  {  

                                         //OLED_WriteRAM(spidev, TextColor);

                                        buf[k] =(u8)(TextColor >> 8); 

                                        buf[k+1] = (u8)TextColor &0x0f;  

                                  }

                                 k +=2;

                         }

                      }

                  

               for(i=0;i<(CharWidth-(multiple-1)*8);i++)  

               {

                          if((buffer[index*multiple+j]&(0x80>>i))== 0x00)  

                          {  

                                  //OLED_WriteRAM(spidev,BackColor);  

                                 buf[k] =(u8)(BackColor >> 8);

                                 buf[k+1] = (u8)BackColor &0x0f; 

                          }  

                          else  

                          {  

                                   //OLED_WriteRAM(spidev, TextColor);  

                                  buf[k] = (u8)(TextColor >> 8);

                                  buf[k+1] = (u8)TextColor &0x0f;

                          }

                          k += 2;

               }

      }   

      printk("\nk = :%d\n", k);

      oled_WriteLongData(spidev, buf, k -2);

      kfree(buf);

}  

 

三、android测试程序

1.         mainactivity.java

packagecom.example.spitest;

 

importcom.friendlyarm.AndroidSDK.HardwareControler;

importcom.hardware.Hardware;

importandroid.os.Bundle;

importandroid.app.Activity;

importandroid.view.Menu;

importandroid.view.View;

import android.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.Toast;

 

public classMainActivity extends Activity {

      

       Button send;

       Button close;

       Button oled_on;

       Button oled_off;

      

    String device = "/dev/spidev0.0";

    int fd_spi;

    int fd_gpio;

    Hardware hardware=new  Hardware();

 

       @Override

       protected void onCreate(BundlesavedInstanceState) {

              super.onCreate(savedInstanceState);

              setContentView(R.layout.activity_main);

             

              System.out.println("openSPI:"+(fd_spi=hardware.openSPI()));

              //System.out.println("openGPIO:"+(fd_gpio=hardware.openGPIO()));

              //hardware.setGPIO(0,20);//RES(115)

              //hardware.setGPIO(1, 20);

              //hardware.setGPIO(0, 20);

              //System.out.println("setGPIO:"+hardware.setGPIO(0,18));

             

              send = (Button)findViewById(R.id.button1);

              send.setOnClickListener(newOnClickListener() {

 

            public void onClick(View arg0) {

                   System.out.println(">>>>>>>>>>>>>>>>transfer:"+hardware.transfer(fd_spi,0xa5));

                   //System.out.println(">>>>>>>>>>reset"+hardware.reset());

 

                   try{

                                   Thread.sleep(1);

                            } catch(InterruptedException e) {

                                   // TODOAuto-generated catch block

                                   e.printStackTrace();

                            }

                   //ssd1353_init();

                   //write_blue_data();

                            //System.out.println("transfer");

                            //System.out.println(">>>>>>>>>>setGPIO"+hardware.setGPIO(35,101));

                   //System.out.println("write_blue_data");

            }

 

        });

             

             

              close =(Button)findViewById(R.id.button2);

              close.setOnClickListener(newOnClickListener() {

 

            public void onClick(View arg0) {

                  

                          hardware.closeSPI();

                          android.os.Process.killProcess(android.os.Process.myPid());

                    System.exit(0);

            }

 

        });

             

              oled_on =(Button)findViewById(R.id.button3);

              oled_on.setOnClickListener(newOnClickListener() {

 

            public void onClick(View arg0) {

                   hardware.sleep(fd_spi,0);

 

            }

 

        });

             

              oled_off = (Button)findViewById(R.id.button4);

              oled_off.setOnClickListener(newOnClickListener() {

 

            public void onClick(View arg0) {

                   hardware.sleep(fd_spi,1);

 

            }

 

        });

      

       }

      

 

       @Override

       public boolean onCreateOptionsMenu(Menu menu){

              // Inflate the menu; this addsitems to the action bar if it is present.

              getMenuInflater().inflate(R.menu.main,menu);

              return true;

       }

 

}

 

Hareware.java

package com.hardware;

 

public class Hardware {

   

    public native int openGPIO();

    public native int openSPI();

    public native int transfer(int fd,int cmd );

    public native int sleep(int fd,int cmd );

    public native int setGPIO(int state,int port);

    public native int reset();

    public native int closeSPI();

 

    public native String  unimplementedStringFromJNI();

 

    static {

        System.loadLibrary("hardware_jni");

    }

 

 

}

 

Hardware_jni.c

#include <stdio.h>

#include <stdlib.h>

#include <linux/input.h>

#include <string.h>

#include <jni.h>

#include <fcntl.h> /*包括文件操作,如open() read() close()write()*/

 

#include <stdint.h>

#include <unistd.h>

#include <getopt.h>

#include <sys/ioctl.h>

#include <linux/types.h>

 

 

#define SPI_CPHA     0x01

#define SPI_CPOL     0x02

 

#define SPI_MODE_0       (0|0)

#define SPI_MODE_1       (0|SPI_CPHA)

#define SPI_MODE_2       (SPI_CPOL|0)

#define SPI_MODE_3       (SPI_CPOL|SPI_CPHA)

 

#define SPI_CS_HIGH      0x04

#define SPI_LSB_FIRST       0x08

#define SPI_3WIRE    0x10

#define SPI_LOOP     0x20

#define SPI_NO_CS    0x40

#define SPI_READY    0x80

#define SPI_IOC_MAGIC           'k'

 

struct spi_ioc_transfer {

    __u64      tx_buf //用于其他数据buffer,如图片类

    __u64      rx_buf;

 

    __u32      len;//buffer长度,即多少字节

    __u32      speed_hz;

 

    __u16      delay_usecs;   //传输延时

    __u8       bits_per_word; //传输位数

    __u8       cs_change //SPI通道选择,本OLED模块固定选0

 

    __u8       XSpos //x起始地址

    __u8       XCpos //x结束地址

    __u8       YSpos //y起始地址

    __u8       YCpos //y结束地址

 

    __u16      Color //控制颜色

    __u64  Charfont; //字库数组地址

       __u8   CharWidth;//文字宽

       __u8   CharHeight;//文字高

       __u8   Words; //文字数目

       __u8   Status;       //The screen switch state, such as: 1, close to 0

       __u16  BackColor; //文字背景颜色

       __u16  TextColor; //文字颜色

       __u16  CharSize //整个字所占字节数

};

 

/* not all platforms use<asm-generic/ioctl.h> or _IOC_TYPECHECK() ... */

#define SPI_MSGSIZE(N) \

    ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \

       ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0)

#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])

 

 

/* Read / Write of SPI mode(SPI_MODE_0..SPI_MODE_3) */

#define SPI_IOC_RD_MODE         _IOR(SPI_IOC_MAGIC,1, __u8)

#define SPI_IOC_WR_MODE         _IOW(SPI_IOC_MAGIC,1, __u8)

 

/* Read / Write SPI bitjustification */

#define SPI_IOC_RD_LSB_FIRST       _IOR(SPI_IOC_MAGIC,2, __u8)

#define SPI_IOC_WR_LSB_FIRST       _IOW(SPI_IOC_MAGIC,2, __u8)

 

/* Read / Write SPI deviceword length (1..N) */

#define SPI_IOC_RD_BITS_PER_WORD   _IOR(SPI_IOC_MAGIC,3, __u8)

#define SPI_IOC_WR_BITS_PER_WORD   _IOW(SPI_IOC_MAGIC,3, __u8)

 

/* Read / Write SPI devicedefault max speed hz */

#define SPI_IOC_RD_MAX_SPEED_HZ    _IOR(SPI_IOC_MAGIC,4, __u32)

#define SPI_IOC_WR_MAX_SPEED_HZ    _IOW(SPI_IOC_MAGIC,4, __u32)

 

#define SPI_IOC_OLED_INIT       _IOR(SPI_IOC_MAGIC,5, __u32)

 

/* set oled cursor postion*/

#define SPI_IOC_SET_CURSOR      _IOR(SPI_IOC_MAGIC,6, __u32)

 

/* set oled  char font*/

#define SPI_IOC_SET_FONT        _IOR(SPI_IOC_MAGIC,7, __u32)

 

/* clear screen buffer*/

#define SPI_IOC_CLEAR_SCREEN    _IOR(SPI_IOC_MAGIC,8, __u32)

 

/* open oled screen*/

#define SPI_IOC_SCREEN_SLEEP    _IOR(SPI_IOC_MAGIC,9, __u32)

 

/* send string*/

#define SPI_IOC_SEND_STRING _IOR(SPI_IOC_MAGIC,10, __u32)

 

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

 

int fd_gpio;

int fd_spi;

int fd_oled;

static uint8_t mode;

static uint8_t bits = 8;

static uint32_t speed = 1000000;

static uint16_t delay;

 

 

 

jstring

Java_com_hardware_Hardware_stringFromJNI( JNIEnv* env,

                                                  jobject thiz )

{

 

    return (*env)->NewStringUTF(env, "keys from JNI create by xu !");

}

 

jint Java_com_hardware_Hardware_openSPI(JNIEnv* env,

        jobject thiz )

{

       int ret = 0;

    fd_spi = open("/dev/spidev0.0", O_RDWR);

   

    if (ioctl(fd_spi, SPI_IOC_WR_MODE, &mode) == -1)

       ret =-2;

 

    if (ioctl(fd_spi, SPI_IOC_RD_MODE, &mode) == -1)

       ret =-3;

 

    if (ioctl(fd_spi, SPI_IOC_WR_BITS_PER_WORD, &bits) ==-1)

       ret =-4;

 

    if (ioctl(fd_spi, SPI_IOC_RD_BITS_PER_WORD, &bits) ==-1)

       ret =-5;

 

    if (ioctl(fd_spi, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1)

       ret =-6;

 

    if (ioctl(fd_spi, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1)

       ret =-7;

    //fd_oled = open("sys/class/spidev/spidev0.0/open",O_RDWR);

 

    if (ioctl(fd_spi, SPI_IOC_OLED_INIT, NULL) == -1)

           ret =-15;

 

    //read(fd_oled, &ret, 0);

 

    //while(1){

    //  read(fd_oled,&ret, 0);

    //  sleep(1);

    //}

    return fd_spi;

}

 

jint Java_com_hardware_Hardware_transfer(JNIEnv* env,

        jobject thiz,jint fd_spi,jint cmd )

{

       int ret, i;

       uint8_t *buf;

       uint16_t tmp = 0xf800;

       uint8_t testfont[] = {

               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x7F,0xE0,0x00,0x00,0x7F,0xE0,0x00,0x00,0x71,0xE0,0x00,

                  0x00,0x30,0xE0,0x00,0x00,0x30,0xE0,0x00,0x00,0x30,0xE0,0x00,0x00,0x30,0xE0,0x00,

                  0x00,0x3E,0xE0,0x00,0x00,0x3F,0xE0,0x00,0x00,0x73,0xE0,0x00,0x00,0x70,0x60,0x00,

                  0x00,0xE0,0x70,0x00,0x00,0xE0,0x78,0x00,0x03,0xC0,0x3E,0x02,0x7F,0x80,0x3F,0xFC,

                  0x3F,0x80,0x1F,0xFC,0x1E,0x00,0x07,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"",0*/

 

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,

                  0x00,0x07,0x80,0x00,0x00,0x07,0xF0,0x00,0x00,0x03,0xF8,0x00,0x00,0x00,0x00,0x00,

                  0x3F,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFC,0x7C,0x03,0x81,0xFC,0x00,0x03,0x80,0x18,

                  0x00,0x07,0xF0,0x00,0x00,0x07,0xFF,0x80,0x00,0x0F,0x07,0x80,0x00,0x1E,0x07,0x00,

                  0x00,0x3C,0x07,0x00,0x00,0x78,0x07,0x00,0x01,0xF0,0x06,0x00,0x07,0xE0,0x0E,0x00,

                  0x1F,0xC8,0x1E,0x00,0x7F,0x0E,0xFC,0x00,0x3C,0x07,0xF8,0x00,0x00,0x01,0xE0,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"",1*/

 

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x30,0x38,0x00,0x03,0x73,0x38,0x00,0x03,0x77,0x38,0x00,0x01,0xF4,0x38,0x00,

                  0x0F,0xFF,0x3F,0xF0,0x1F,0xFF,0x3F,0xF0,0x01,0xB4,0x63,0x00,0x03,0xBE,0x63,0x00,

                  0x07,0x26,0xE3,0x00,0x08,0x61,0xB7,0x00,0x18,0xF8,0x1E,0x00,0x3F,0xFF,0x1E,0x00,

                  0x61,0x8C,0x0F,0x00,0x01,0xDC,0x1F,0xC0,0x00,0xF8,0x3B,0xF0,0x00,0x7E,0x71,0xFE,

                  0x07,0xEE,0xE0,0xFE,0x0F,0x01,0xC0,0x7C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"",2*/

 

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

                  0x00,0x01,0x01,0x80,0x08,0x03,0xFF,0x80,0x1F,0xFF,0xFF,0x80,0x1F,0x80,0x81,0x80,

                  0x01,0x80,0xC1,0x80,0x03,0x00,0xC1,0x80,0x03,0x00,0xC1,0x80,0x07,0x01,0xC1,0x80,

                  0x0F,0x99,0xC1,0x80,0x1F,0xF9,0xC1,0x9C,0x7B,0x11,0xFF,0xFC,0x73,0x11,0x80,0x3C,

                  0x03,0x10,0x00,0x1C,0x03,0xF7,0xFF,0x9C,0x07,0xFF,0xFF,0x9C,0x00,0x04,0x00,0x38,

                  0x00,0x00,0x00,0x38,0x00,0x00,0x07,0xF8,0x00,0x00,0x03,0xF0,0x00,0x00,0x00,0x00,

                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"",3*/

       };

 

       uint8_t testfont1[] = {

               0x00,0x00,0x0F,0xE0,0x08,0x20,0x08,0x20,0x08,0x20,0x0A,0x20,0x09,0x20,0x08,0xA0,

               0x08,0xA0,0x08,0x20,0x10,0x20,0x10,0x22,0x20,0x22,0x20,0x22,0x40,0x1E,0x80,0x00,/*"",0*/

 

               0x02,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x04,0x00,0x04,0x00,0x04,0x00,0x07,0xF0,

               0x04,0x10,0x04,0x10,0x04,0x10,0x08,0x10,0x08,0x10,0x10,0x10,0x20,0xA0,0x40,0x40,/*"",1*/

 

               0x08,0x20,0x49,0x20,0x2A,0x20,0x08,0x3E,0xFF,0x44,0x2A,0x44,0x49,0x44,0x88,0xA4,

               0x10,0x28,0xFE,0x28,0x22,0x10,0x42,0x10,0x64,0x28,0x18,0x28,0x34,0x44,0xC2,0x82,/*"",2*/

 

               0x00,0x00,0x01,0xF8,0xFC,0x08,0x10,0x08,0x10,0x88,0x20,0x88,0x3C,0x88,0x64,0xFE,

               0x64,0x02,0xA4,0x02,0x24,0x02,0x25,0xFA,0x3C,0x02,0x24,0x02,0x20,0x14,0x00,0x08,/*"",3*/

 

               0x02,0x00,0x02,0x00,0xFF,0xFE,0x04,0x00,0x04,0x00,0x0F,0xF0,0x08,0x10,0x18,0x10,

               0x2F,0xF0,0x48,0x10,0x88,0x10,0x0F,0xF0,0x08,0x10,0x08,0x10,0x08,0x50,0x08,0x20,/*"",4*/

 

               0x00,0x00,0x7B,0xF8,0x4A,0x08,0x52,0x08,0x53,0xF8,0x62,0x08,0x52,0x08,0x4B,0xF8,

               0x4A,0x44,0x4A,0x48,0x6A,0x30,0x52,0x20,0x42,0x10,0x42,0x88,0x43,0x06,0x42,0x00,/*"",5*/

 

               0x00,0x80,0x04,0x80,0x04,0x80,0x08,0x40,0x08,0x40,0x10,0x20,0x20,0x10,0x42,0x08,

               0x82,0x06,0x04,0x00,0x04,0x40,0x08,0x20,0x10,0x20,0x3F,0xF0,0x10,0x10,0x00,0x00,/*"",6*/

 

               0x00,0x00,0x3F,0xF8,0x00,0x08,0x00,0x08,0x7F,0xE8,0x00,0x08,0x00,0x08,0x1F,0x88,

               0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x1F,0x88,0x10,0x88,0x00,0x28,0x00,0x10,/*"",7*/

       };

 

       buf = malloc(sizeof(uint8_t) * 160 * 128);

 

       for(i = 0; i < 160 * 128; i+=2){

           //memcopy(buf++,tmp, sizeof(uint16_t));

           buf[i] = 0x00;

           buf[i+1] = 0xf8;

       }

#if 1

    struct spi_ioc_transfer tr = {

       .len = 4,

       //.len = 1,

       .delay_usecs = delay,

       .speed_hz = speed,

       .bits_per_word = bits,

       .XSpos = 0,

       .XCpos = 70,

       .YSpos = 30,

       .YCpos = 70,

       .Color = 0x3333,

       .Charfont = (unsigned long)testfont1,

       .CharWidth = 16,

        .CharHeight =16,

       .BackColor = 0x02ef,

       .TextColor = 0xf800,

       .CharSize = 16 * 2,

       .Words = 8,

    };

    ret = ioctl(fd_spi, SPI_IOC_SET_FONT, &tr);

    ret = ioctl(fd_spi, SPI_IOC_SET_CURSOR, &tr);

    struct spi_ioc_transfer tr1 = {

           .tx_buf = (unsigned long)buf,

           .len = 4096,

           //.len =1,

           .delay_usecs = delay,

           .speed_hz = speed,

           .bits_per_word = bits,

           .XSpos = 30,

           .XCpos = 70,

           .YSpos = 30,

           .YCpos = 70,

           .Color = 0x3333,

       };

 

    ret = ioctl(fd_spi, SPI_IOC_SEND_STRING, &tr1);

    if (ret < 1)

       //return ret;

#endif

    free(buf);

    //read(fd_oled, &ret, 0);

    return 0;

}

 

jint Java_com_hardware_Hardware_sleep(JNIEnv* env,

        jobject thiz,jint fd_spi,jint cmd )

{

    int ret;

    struct spi_ioc_transfer tr = {

              .Status = cmd,

           };

    ret = ioctl(fd_spi, SPI_IOC_SCREEN_SLEEP, &tr);

 

    return ret;

}

 

 

jint Java_com_hardware_Hardware_closeSPI(JNIEnv* env,

        jobject thiz )

{

    close(fd_spi);

 

    return 1;

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值