It's nucleo f4 DMA trandfer for ov7670&ILI9341.

Dependencies:   mbed ILI9341_SPI OV7670_SCCB

main.cpp

Committer:
tmnt
Date:
2016-04-04
Revision:
2:de327fb4e2c5
Parent:
0:ce10b2e08479
Child:
3:901230f7d62b

File content as of revision 2:de327fb4e2c5:

#include "mbed.h"
#include "TIM_DMAInit.h"
#include "SPI_DMAInit.h"


/*

  ********ov7670********
   +3V3 - 3V3         GND-GND
  PC_12 - SIOC        SIDO - PC10
   PD_2 - VSYNC       HREF - A3
  B4,A4 - PCLK        XCLK - PC_9
   PB_7 - D7          D6 - PB_6
   PB_5 - D5          D4 - PB_4
   PB_3 - D3          D2 - PB_2
   PB_1 - D1          D0 - PB_0
+3V3-330Ω-RESET

  ********74HC00*********
A1          VCC - +5V
B1          B4 -- PCLK
Y1          A4 -- PCLK
A2          Y4 - B3
B2          B3 - Y4
Y2          A3 - HREF
GND         Y3 - PA8

  ********ILI9341*********
SDO - PA6
LED - 100Ω - +5V
SCK - PA5
SDI - PA7
DC  - PA_4
RS  - PA_12
CS  - PA_11
GND - GND
VCC - +5V

  ********NUCLEOF401RE*******

U5V×
E5V○

*/





 
#define REG_COM1        0x04    /* Control 1 */
#define REG_COM6        0x0f    /* Control 6 */
#define REG_AECH        0x10    /* More bits of AEC value */
#define REG_CLKRC       0x11    /* Clocl control */
#define CLK_EXT         0x40    /* Use external clock directly */
#define CLK_SCALE       0x3f    /* Mask for internal clock scale */
#define REG_COM7        0x12    /* Control 7 */
#define COM7_RESET      0x80    /* Register reset */
#define COM7_FMT_MASK   0x38
#define COM7_FMT_VGA    0x00
#define COM7_FMT_CIF    0x20    /* CIF format */
#define COM7_FMT_QVGA   0x10    /* QVGA format */
#define COM7_FMT_QCIF   0x08    /* QCIF format */
#define COM7_RGB        0x04    /* bits 0 and 2 - RGB format */
#define COM7_YUV        0x00    /* YUV */
#define COM7_BAYER      0x01    /* Bayer format */
#define COM7_PBAYER     0x05    /* "Processed bayer" */
#define REG_COM8        0x13    /* Control 8 */
#define REG_COM9        0x14    /* Control 9  - gain ceiling */
#define REG_TSLB        0x3a    /* lots of stuff */
#define REG_COM15       0x40    /* Control 15 */
#define COM15_R10F0     0x00    /* Data range 10 to F0 */
#define COM15_R01FE     0x80    /*            01 to FE */
#define COM15_R00FF     0xc0    /*            00 to FF */
#define COM15_RGB565    0x10    /* RGB565 output */
#define COM15_RGB555    0x30    /* RGB555 output */
#define REG_COM16       0x41    /* Control 16 */
#define COM16_AWBGAIN   0x08    /* AWB gain enable */
#define REG_COM17       0x42    /* Control 17 */
#define COM17_AECWIN    0xc0    /* AEC window - must match COM4 */
#define COM17_CBAR      0x08    /* DSP Color bar */
#define REG_CMATRIX_BASE 0x4f
#define CMATRIX_LEN 6
#define REG_CMATRIX_SIGN 0x58
#define REG_BRIGHT      0x55    /* Brightness */
#define REG_CONTRAS     0x56    /* Contrast control */

#define REG_GFIX        0x69    /* Fix gain control */

#define REG_REG76       0x76    /* OV's name */
#define R76_BLKPCOR     0x80    /* Black pixel correction enable */
#define R76_WHTPCOR     0x40    /* White pixel correction enable */

#define REG_RGB444      0x8c    /* RGB 444 control */
#define R444_ENABLE     0x02    /* Turn on RGB444, overrides 5x5 */
#define R444_RGBX       0x01    /* Empty nibble at end */

#define REG_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
#define REG_HAECC2      0xa0    /* Hist AEC/AGC control 2 */

#define REG_BD50MAX     0xa5    /* 50hz banding step limit */
#define REG_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
#define REG_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
#define REG_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
#define REG_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
#define REG_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
#define REG_BD60MAX     0xab    /* 60hz banding step limit */



uint8_t dma_buf[145][300];
uint8_t flag_dma;



InterruptIn VSYNC(PD_2);

SPI spi(PA_7,PA_6,PA_5);

DigitalOut dc(PA_4);
DigitalOut rs(PA_12);
DigitalOut cs(PA_11);

DigitalInOut SDA(PC_10);
DigitalInOut SCL(PC_12);

PortIn cdata(PortB, 0x00ff);

void window (unsigned int x, unsigned int y, unsigned int w, unsigned int h);
void pixel(int x, int y, int color);
void vline(int x, int y0, int y1, int color);
void circle(int x0, int y0, int r, int color);
void fillcircle(int x0, int y0, int r, int color);
void fillrect(int x0, int y0, int x1, int y1, int color);
void wr_cmd(unsigned char cmd);
void wr_dat(unsigned char dat);
char rd_byte(unsigned char cmd);
int rd_32(unsigned char cmd);
int  Read_ID(void);
void tft_reset();
void fillrect(int x0, int y0, int x1, int y1, int color);

void I2cstart(void);
void I2cstop(void);
void I2cout(unsigned char datar);
void c(unsigned char adrs,unsigned char datak);
void cam_init();

void camdma_start();

void test_color();




int main() {


 GPIO_InitTypeDef gpioconf1; 
    __GPIOB_CLK_ENABLE();
     gpioconf1.Pin = GPIO_PIN_8 |   GPIO_PIN_9  |   GPIO_PIN_10 |   GPIO_PIN_11 |   GPIO_PIN_12 |   GPIO_PIN_13 |GPIO_PIN_14    |   GPIO_PIN_15;//pa13
    gpioconf1.Mode = GPIO_MODE_INPUT;
    gpioconf1.Pull = GPIO_PULLDOWN;
    gpioconf1.Speed = GPIO_SPEED_HIGH; 
    HAL_GPIO_Init(GPIOB, &gpioconf1);
   
   
   HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_HSE, RCC_MCODIV_1); 
 
     GPIO_InitTypeDef GPIO_InitStruct; 
  /*Configure GPIO pin : PC9 MCO2 for cam XCLK*/    
  __GPIOC_CLK_ENABLE();    
  GPIO_InitStruct.Pin = GPIO_PIN_9;    
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;    
  GPIO_InitStruct.Pull = GPIO_NOPULL;    
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;    
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;    
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    // spi_Init();
    dma_init();
   
    spi.format(8,3);
    spi.frequency(20000000); 
    tft_reset(); 

 __disable_irq();
 
 VSYNC.rise(&camdma_start);//PCLK割り込み    
 cam_init();

fillrect(0,0,150,290,0xf800);//red


wait(1);
 wr_cmd(0x2C);
 spi.write(0x66);
 spi_Init();
 
  __enable_irq();
  
  
    while(1) {
        }
}




void wr_cmd(unsigned char cmd)
{
    dc = 0;
    cs = 0;
    spi.write(cmd);      // mbed lib
    dc = 1;
}
void wr_dat(unsigned char dat)
{
   spi.write(dat);      // mbed lib
}
char rd_byte(unsigned char cmd)
{
    char r;
    dc = 0;
    cs = 0;
    spi.write(cmd);      // mbed lib
    cs = 1;
    r = spi.write(0xff);
    cs = 1;    
    return(r);
}
 
// read 32 bit
int rd_32(unsigned char cmd)
{
    int d;
    char r;
    dc = 0;
    cs = 0;
    d = cmd;
    d = d << 1;
    spi.format(9,3);    // we have to add a dummy clock cycle
    spi.write(d);
    spi.format(8,3);   
    dc = 1;
    r = spi.write(0xff);
    d = r;
    r = spi.write(0xff);
    d = (d << 8) | r;
    r = spi.write(0xff);
    d = (d << 8) | r;
    r = spi.write(0xff);
    d = (d << 8) | r;
    cs = 1;    
    return(d);
}
 
int  Read_ID(void){
    int r;
    r = rd_byte(0x0A);
    r = rd_byte(0x0A);
    r = rd_byte(0x0A);
    r = rd_byte(0x0A);
    return(r);
}
 
 
// Init code based on MI0283QT datasheet
 
void tft_reset()
{
    cs = 1;                           // cs high
    dc = 1;                           // dc high 
    rs = 0;                        // display reset
 
    wait_us(50);
    rs = 1;                       // end hardware reset
    wait_ms(5);
     
    wr_cmd(0x01);                     // SW reset  
    wait_ms(5);
    wr_cmd(0x28);                     // display off  
 
    /* Start Initial Sequence ----------------------------------------------------*/
     wr_cmd(0xCF);                     
     spi.write(0x00);
     spi.write(0x83);
     spi.write(0x30);
     cs = 1;
     
     wr_cmd(0xED);                     
     spi.write(0x64);
     spi.write(0x03);
     spi.write(0x12);
     spi.write(0x81);
     cs = 1;
     
     wr_cmd(0xE8);                     
     spi.write(0x85);
     spi.write(0x01);
     spi.write(0x79);
     cs = 1;
     
     wr_cmd(0xCB);                     
     spi.write(0x39);
     spi.write(0x2C);
     spi.write(0x00);
     spi.write(0x34);
     spi.write(0x02);
     cs = 1;
           
     wr_cmd(0xF7);                     
     spi.write(0x20);
     cs = 1;
           
     wr_cmd(0xEA);                     
     spi.write(0x00);
     spi.write(0x00);
     cs = 1;
     
     wr_cmd(0xC0);                     // POWER_CONTROL_1
     spi.write(0x26);
     cs = 1;
 
     wr_cmd(0xC1);                     // POWER_CONTROL_2
     spi.write(0x11);
     cs = 1;
     
     wr_cmd(0xC5);                     // VCOM_CONTROL_1
     spi.write(0x35);
     spi.write(0x3E);
     cs = 1;
     
     wr_cmd(0xC7);                     // VCOM_CONTROL_2
     spi.write(0xBE);
     cs = 1; 
     
     wr_cmd(0x36);                     // MEMORY_ACCESS_CONTROL
     spi.write(0x48);
     cs = 1; 
     
     wr_cmd(0x3A);                     // COLMOD_PIXEL_FORMAT_SET
     spi.write(0x55);                 // 16 bit pixel 
     cs = 1;
     
     wr_cmd(0xB1);                     // Frame Rate
     spi.write(0x00);
     spi.write(0x1B);               
     cs = 1;
     
     wr_cmd(0xF2);                     // Gamma Function Disable
     spi.write(0x08);
     cs = 1; 
     
     wr_cmd(0x26);                     
     spi.write(0x01);                 // gamma set for curve 01/2/04/08
     cs = 1; 
     
     wr_cmd(0xE0);                     // positive gamma correction
     spi.write(0x1F); 
     spi.write(0x1A); 
     spi.write(0x18); 
     spi.write(0x0A); 
     spi.write(0x0F); 
     spi.write(0x06); 
     spi.write(0x45); 
     spi.write(0x87); 
     spi.write(0x32); 
     spi.write(0x0A); 
     spi.write(0x07); 
     spi.write(0x02); 
     spi.write(0x07);
     spi.write(0x05); 
     spi.write(0x00);
     cs = 1;
     
     wr_cmd(0xE1);                     // negativ gamma correction
     spi.write(0x00); 
     spi.write(0x25); 
     spi.write(0x27); 
     spi.write(0x05); 
     spi.write(0x10); 
     spi.write(0x09); 
     spi.write(0x3A); 
     spi.write(0x78); 
     spi.write(0x4D); 
     spi.write(0x05); 
     spi.write(0x18); 
     spi.write(0x0D); 
     spi.write(0x38);
     spi.write(0x3A); 
     spi.write(0x1F);
     cs = 1;
     
     wr_cmd(0x2A);
    spi.write(0);
    spi.write(0);
    spi.write(0);
    spi.write(0x95);
    
    cs = 1;
    wr_cmd(0x2B);
    spi.write(0);
    spi.write(0);
    spi.write(0x00);
    spi.write(0x90);
    cs = 1;
     
     //wr_cmd(0x34);                     // tearing effect off
     //_cs = 1;
     
     //wr_cmd(0x35);                     // tearing effect on
     //_cs = 1;
      
     wr_cmd(0xB7);                       // entry mode
     spi.write(0x07);
     cs = 1;
     
     wr_cmd(0xB6);                       // display function control
     spi.write(0x0A);
     spi.write(0x82);
     spi.write(0x27);
     spi.write(0x00);
     cs = 1;
     
     wr_cmd(0x11);                     // sleep out
     cs = 1;
     
     wait_ms(100);
     
     wr_cmd(0x29);                     // display on
     cs = 1;
     
     wait_ms(100);
     
 }
 void pixel(int x, int y, int color)
{
    wr_cmd(0x2A);
    spi.write(x >> 8);
    spi.write(x);
    cs = 1;
    wr_cmd(0x2B);
    spi.write(y >> 8);
    spi.write(y);
    cs = 1;
    wr_cmd(0x2C);  // send pixel
    //#if defined TARGET_KL25Z  // 8 Bit SPI
    spi.write(color >> 8);
    spi.write(color & 0xff);
    /*#else 
    SPI::format(16,3);                            // switch to 16 bit Mode 3
    SPI::write(color);                              // Write D0..D15
    SPI::format(8,3);
    #endif*/
    cs = 1;
}

void window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
    wr_cmd(0x2A);
    spi.write(x >> 8);
    spi.write(x);
    spi.write((x+w-1) >> 8);
    spi.write(x+w-1);
    
    cs = 1;
    wr_cmd(0x2B);
    spi.write(y >> 8);
    spi.write(y);
    spi.write((y+h-1) >> 8);
    spi.write(y+h-1);
    cs = 1;
}

void vline(int x, int y0, int y1, int color)
{
    int h;
    h = y1 - y0 + 1;
    window(x,y0,1,h);
    wr_cmd(0x2C);  // send pixel
    //#if defined TARGET_KL25Z  // 8 Bit SPI
    for (int y=0; y<h; y++) {
        spi.write(color >> 8);
        spi.write(color & 0xff);
    } 
  /*  #else 
    SPI::format(16,3);                            // switch to 16 bit Mode 3
    for (int y=0; y<h; y++) {
        SPI::write(color);
    }
    SPI::format(8,3);*/
    //#endif
    cs = 1;
    //WindowMax();
    return;
}

void fillcircle(int x0, int y0, int r, int color)
{
    int x = -r, y = 0, err = 2-2*r, e2;
    do {
        vline(x0-x, y0-y, y0+y, color);
        vline(x0+x, y0-y, y0+y, color);
        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);
}


void circle(int x0, int y0, int r, int color)
{
 
    int x = -r, y = 0, err = 2-2*r, e2;
    do {
        pixel(x0-x, y0+y,color);
        pixel(x0+x, y0+y,color);
        pixel(x0+x, y0-y,color);
        pixel(x0-x, y0-y,color);
        e2 = err;
        if (e2 <= y) {
            err += ++y*2+1;
            if (-x == y && e2 <= x) e2 = 0;
        }
        if (e2 > x) err += ++x*2+1;
    } while (x <= 0);
    }
 void fillrect(int x0, int y0, int x1, int y1, int color)
{
 
    int h = y1 - y0 + 1;
    int w = x1 - x0 + 1;
    int pixel = h * w;
    //window(x0,y0,w,h);
    wr_cmd(0x2C);  // send pixel 
    //#if defined TARGET_KL25Z  // 8 Bit SPI
    for (int p=0; p<pixel; p++) {
        spi.write(color >> 8);
        spi.write(color & 0xff);
    }
   /*#else
    SPI::format(16,3);                            // switch to 16 bit Mode 3
    for (int p=0; p<pixel; p++) {
        SPI::write(color);
    }
    SPI::format(8,3);
    #endif*/
    cs = 1;
    //WindowMax();
    return;
}

void I2cstart(void)
{
SDA=1;SCL=1;        /* SCL,SDAは常時Highとする */
        wait_us(2);
      SDA=0;
      wait_us(2);                                   // SDA出力
}

 void I2cstop(void)
{
          SCL=0;                                                // 先にSDA Low
        wait_us(2);
        SDA=0;                                              // SCL Low
        wait_us(2);
       SCL=1;                                          // SDA Low                                      // 出力モードに戻す SDA =Low
        wait_us(2);
         SDA=1;                                             // 先にSCLをHigh
        wait_us(2);
                                                        // 後からSDAをHigh

}
  void I2cout(unsigned char datar)
{
        int ia;
       for(ia=0;ia<8;ia++){
          SCL=0;
          if(datar & 0x80){SDA=1;}
          else SDA=0;
          datar<<=1;
           wait_us(1);
          SCL=1;
          wait_us(2);
          SCL=0;
          wait_us(1);//wait();
       }
        wait_us(1);
          
          SCL=1;
          datar<<=1;
          wait_us(2);
          SCL=0;
           
           wait_us(1);
}


      void c(unsigned char adrs,unsigned char datak)
{
    I2cstart();
    I2cout(0x42);
    I2cout(adrs);
    I2cout(datak);
    I2cstop();
         wait_ms(10);
}


void cam_init(){
        c(REG_COM7, COM7_RESET);                        //0x12:COM7(Reset,QCIF,Cbar,RGBformat)
        wait_ms(200);                                                //200ms

        c(REG_COM7,COM7_RGB|COM7_FMT_QCIF);                //0x12:COM7        ,  0x0C)        //QCIF, RGB
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
        c(REG_RGB444, 0x00);        //0x8c:RGB 444 control
        c(REG_COM1, 0x00); //0x40                                               //0x04:COM1(CCIR656,AEC)        //0)        //0x40)
        c(REG_COM15, COM15_R01FE|COM15_RGB565);        //0x40:COM15

        c(REG_COM9, 0x48);                        // 38 0x14:COM9=max AGC gain ceiling, Freeze AGC/AEC

       //c(0x3d,0xc3);        //(REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2)        //0x3d:COM13
        c(REG_HAECC7,0x94);                //0xaa:Hist AEC/AGC control 7        c(0xAA,0x94)        //AEC algorithm

        c(REG_TSLB,0x04);                //0x3a:Neg,UVval,YUYV,window        TSLB_YLAST)                //0x04)        //0x0C)        //0x80)        //0x00)        //0x04)
        c(0x20,0x04);                        //ADCCTR0, A/D range&ref, mu0102

        /******* ringo *********/
       c(REG_COM8,0xfd); //AGC,AWB OFF,res OK

         c(0x10,0x0f);//AECコントロール(中位ビット)
         c(0x07,0x00);//AECコントロール(上位ビット)
        //by Mr.Shiono

        c(0x01,0x40);
        c(0x02,0x60);
        c(0x03,0x0a);
        c(0x0c,0x00);
        c(0x0e,0x61);
        c(0x0f,0x4b);
        c(0x15,0x00);
        c(0x16,0x02);
        c(0x17,0x18); //HSTART
        c(0x18,0x01);
        c(0x19,0x02);
        c(0x1a,0x7a);
        c(0x1e,0x07);
        c(0x21,0x02);
        c(0x22,0x91);
        c(0x29,0x07);
        c(0x32,0xb6);
        c(0x33,0x0b);
        c(0x34,0x11);
        c(0x35,0x0b);
        c(0x37,0x1d);
        c(0x38,0x71);
        c(0x39,0x2a);
        c(0x3b,0x92);//com11 ナイトモード
        c(0x3c,0x78);
        c(0x3d,0xc3);
        c(0x3e,0x00);
        c(0x3f,0x00);
        c(0x41,0x08);
        c(0x41,0x38);
        c(0x43,0x0a);
        c(0x44,0xf0);
        c(0x45,0x34);
        c(0x46,0x58);
        c(0x47,0x28);
        c(0x48,0x3a);
        c(0x4b,0x09);
        c(0x4c,0x00);
        c(0x4d,0x40);
        c(0x4e,0x20);
        c(0x4f,0x80);//c(0x4f,0x80);    彩度調整
        c(0x50,0x80);//c(0x50,0x80);
        c(0x51,0x00);
        c(0x52,0x22);//c(0x52,0x22);
        c(0x53,0x5e);//c(0x52,0x5e);
        c(0x54,0x80);//c(0x54,0x80);
        c(0x56,0x40);
        c(0x58,0x9e);
        c(0x59,0x88);
        c(0x5a,0x88);
        c(0x5b,0x44);
        c(0x5c,0x67);
        c(0x5d,0x49);
        c(0x5e,0x0e);
        c(0x69,0x00);
        c(0x6a,0x40);
        c(0x6b,0x0a);
        c(0x6c,0x0a);
        c(0x6d,0x55);
        c(0x6e,0x11);
        c(0x6f,0x9f);
        c(0x70,0x3a);
        c(0x71,0x35);
        c(0x72,0x11);
        c(0x73,0xf0);
        c(0x74,0x10);
        c(0x75,0x05);
        c(0x76,0xe1);
        c(0x77,0x01);
        c(0x78,0x04);
        c(0x79,0x01);
        c(0x8d,0x4f);
        c(0x8e,0x00);
        c(0x8f,0x00);
        c(0x90,0x00);
        c(0x91,0x00);
        c(0x96,0x00);
        c(0x96,0x00);                        //?
        c(0x97,0x30);
        c(0x98,0x20);
        c(0x99,0x30);
        c(0x9a,0x00);
        c(0x9a,0x84);                        //?
        c(0x9b,0x29);
        c(0x9c,0x03);
        c(0x9d,0x4c);
        c(0x9e,0x3f);
        c(0xa2,0x02);
        c(0xa4,0x88);
        c(0xb0,0x84);
        c(0xb1,0x0c);
        c(0xb2,0x0e);
        c(0xb3,0x82);
        c(0xb8,0x0a);
        c(0xc8,0xf0);
        c(0xc9,0x60);
        c(0x6b,0x40);//入力クロックx4
        c(REG_CLKRC,0x40);   //0xaf                     //PCLK*(1/48)

}



void camdma_start()
{
if(flag_dma==0){
    HAL_DMA_Start_IT(&DMA_HandleType/*DMA初期設定構造体*/, (uint32_t)&GPIOB->IDR/*&0x00ff転送元アドレス*/, (uint32_t)dma_buf/*転送先アドレス*/,43500/*データ転送回数*/);

    HAL_SPI_Transmit_DMA(&spi1, (uint8_t*)dma_buf, sizeof(dma_buf));
    
  // HAL_ADC_Start_DMA(&ADC_1_dma,(uint32_t*)ad_dma_buf,3);
}
flag_dma=1;
}