カメラモジュールから液晶ディスプレイに。 何か映ったけど・・・ 

 

 仕様は決まった。 さっそくプログラムを書いてみた。

とりあえずはこんな感じ。

#include <Wire.h>
#include <FspTimer.h>

static FspTimer fsp_timer;
long putcnt = 0;

void Cam_Write_Reg(uint8_t reg, uint8_t dat){
  Wire.beginTransmission(0x21);
  Wire.write(reg);             // Sends value byte
  Wire.write(dat);             // Sends value byte
  if(Wire.endTransmission(true)){
    Serial.print("error write reg ");
    Serial.println(reg, HEX);
  }
  delay(20);
}

void Cam_Init(void){
  uint8_t error;

  R_PORT0->PDR = 0x0000;
  R_PORT3->PDR = 0x0010;  //XCLKだけ出力
  R_PORT2->PDR = 0x0000;

  //OV7670 XCLK用PWM生成 5MHz D8ポート
  fsp_timer.begin(TIMER_MODE_PWM,0,7, 5000000.0 ,50.0);
  fsp_timer.open();
  R_PFS->PORT[3].PIN[4].PmnPFS_b.PMR = 0;  //D8を汎用入出力に設定
  R_PFS->PORT[3].PIN[4].PmnPFS_b.PSEL = 0x03; //D8をGPT端子として使用
  R_PFS->PORT[3].PIN[4].PmnPFS_b.PMR = 1;  //D8を周辺機能用の端子に設定
  R_GPT7->GTIOR_b.GTIOA = 0x06;  //GTIOCA端子機能選択
  R_GPT7->GTIOR_b.OAE = 1;  //GTIOCA端子出力許可
  fsp_timer.start();  //PWM出力開始

  Wire.begin();  //IIC起動
  while(1){
    Wire.beginTransmission(0x21);  //OV7670と接続
    error = Wire.endTransmission();
    if (error == 0){  //接続確認
      break;
    }else{
      Serial.print("OV7670 conect error : ");
      Serial.println(error);
    }
  }

  //ov7670基本設定
  Cam_Write_Reg(0x12, 0x80);  //REG_COM7  SCCB reset
  delay(100);
  Cam_Write_Reg(0x3a, 0x04);  //REG_TSLB
  Cam_Write_Reg(0x11, 0x0f);  //CLKRC  クロック1/15倍

  //解像度設定 QVGA
  Cam_Write_Reg(0x17, 0x16);  //HSTART
  Cam_Write_Reg(0x18, 0x04);  //HSTOP
  Cam_Write_Reg(0x32, 0x00);  //HREF  QVGA
  Cam_Write_Reg(0x19, 0x02);  //VSTART
  Cam_Write_Reg(0x1a, 0x7a);  //VSTOP
  Cam_Write_Reg(0x03, 0x0a);  //VREF
  Cam_Write_Reg(0x0c, 0x04);  //REG_COM3 
  Cam_Write_Reg(0x3e, 0x19);  //REG_COM14  QVGA
  Cam_Write_Reg(0x70, 0x3a);  //SCALING_XSC  QVGA
  Cam_Write_Reg(0x71, 0x35);  //SCALING_YSC  QVGA
  Cam_Write_Reg(0x72, 0x11);  //Scaling DCWCTR  QVGA
  Cam_Write_Reg(0x73, 0xf1);  //Scaling PCLK_DIV  QVGA
  Cam_Write_Reg(0xa2, 0x02);  //SCALING_PCLK_DELAY  QVGA

  //色データ RGB565
  Cam_Write_Reg(0x12, 0x04);  //REG_COM7  RGB mode Use QVGA
  Cam_Write_Reg(0x8c, 0x00);  //REG_RGB444 RGB444 diseble
  Cam_Write_Reg(0x40, 0xd0);  //REG_COM15  RGB565
  Cam_Write_Reg(0x04, 0x00);  //REG_COM1  
  Cam_Write_Reg(0x14, 0x38);  //REG_COM9
  Cam_Write_Reg(0x4f, 0xb3);  //Color Saturation 0
  Cam_Write_Reg(0x50, 0xb3);
  Cam_Write_Reg(0x51, 0x00);
  Cam_Write_Reg(0x52, 0x3d);
  Cam_Write_Reg(0x53, 0xa7);
  Cam_Write_Reg(0x54, 0xe4);
  Cam_Write_Reg(0x3d, 0x08);  //COM13
  Cam_Write_Reg(0x15, 0x20);  //COM10 //PCLK does not toggle on HBLANK.
}

void Lcd_Writ_Bus(unsigned char d)
{
  R_PORT4->PODR_b.PODR8 = 0;
  R_PORT1->PODR         = d << 2;
  R_PORT4->PODR_b.PODR8 = 1;
}

void Lcd_Write_Com(unsigned char VH)  
{   
  R_PORT4->PODR_b.PODR9 = 0;
  Lcd_Writ_Bus(VH);
}

void Lcd_Write_Data(unsigned char VH)
{
  R_PORT4->PODR_b.PODR9 = 1;
  Lcd_Writ_Bus(VH);
}

void Lcd_Init(void)
{

  R_PFS->PORT[1].PIN[8].PmnPFS_b.PMR = 0;
  R_PFS->PORT[1].PIN[9].PmnPFS_b.PMR = 0;
  R_PORT1->PDR = 0x03fc;  //Data Port
  R_PORT4->PDR = 0x0f00;  //Cont Port

  R_PORT4->PODR_b.PODR8  = 1;  //WR
  R_PORT4->PODR_b.PODR9  = 1;  //RS
  R_PORT4->PODR_b.PODR11 = 1;  //Reset
  delay(5); 
  R_PORT4->PODR_b.PODR11 = 0;
  delay(15);
  R_PORT4->PODR_b.PODR11 = 1;
  delay(15);
  R_PORT4->PODR_b.PODR10 = 0;

  Lcd_Write_Com(0x36);    // Memory Access Control 
  Lcd_Write_Data(0x38);   //横表示  BGR

  Lcd_Write_Com(0x21);    //Display Inversion ON

  Lcd_Write_Com(0x3A);
  Lcd_Write_Data(0x55);  //Data 18bit

  Lcd_Write_Com(0xB1);  //Frame Rate Control
  Lcd_Write_Data(0x00);
  Lcd_Write_Data(0x1b);

  Lcd_Write_Com(0xB6);    // Display Function Control 
  Lcd_Write_Data(0x08);
  Lcd_Write_Data(0x82);
  Lcd_Write_Data(0x27);

  Lcd_Write_Com(0x11);    //Exit Sleep 
  delay(120); 
  Lcd_Write_Com(0x29);    //Display on 
}

void setup(){
  Serial.begin(9600);
  while (!Serial);

  //LCD初期化
  Serial.println("LCD init");
  Lcd_Init();
  //OV7670カメラとの通信開始
  Serial.println("OV7670 init");
  Cam_Init();
  Serial.println("Init Finish");
}

void loop(){
  int i1;

  while(!R_PORT3->PIDR_b.PIDR2);  //VSYNCが立ち上がるまで待ち
  Lcd_Write_Com(0x2a);  //描画領域 幅
  Lcd_Write_Data(0x00);
  Lcd_Write_Data(0x00);
  Lcd_Write_Data(0x01);
  Lcd_Write_Data(0x3f);
  Lcd_Write_Com(0x2b);  //描画領域 高さ
  Lcd_Write_Data(0x00);
  Lcd_Write_Data(0x00);
  Lcd_Write_Data(0x00);
  Lcd_Write_Data(0xEF);
  Lcd_Write_Com(0x2c);

  //画面のドットの数だけ繰り返す
  for(i1 = 0; i1 < 76800; i1++){
    while(!R_PORT3->PIDR_b.PIDR1);  //PCLKが立ち上がるまで待ち
    Lcd_Write_Data(R_PORT0->PIDR | (R_PORT2->PIDR << 1));  //LCDへデータ転送 上位
    while(R_PORT3->PIDR_b.PIDR1);  //PCLKが立ち下がるまで待ち
    while(!R_PORT3->PIDR_b.PIDR1);  //PCLKが立ち上がるまで待ち
      Lcd_Write_Data(R_PORT0->PIDR | (R_PORT2->PIDR << 1));  //LCDへデータ転送 下位
    while(R_PORT3->PIDR_b.PIDR1);  //PCLKが立ち下がるまで待ち
  }
}

 

 まだ最初なので、デバックも兼ねた作りとなっている。

シリアルモニターが開かれないとプログラムがスタートしないようになっているので、実行したらシリアルモニターを開くこと。

また、1枚の画像が表示されるのに3秒くらいかかるよう処理をわざと遅くしている。

まずは綺麗に画像を取得して表示させることが大切だからだ。

 

 で、プログラムを実行すると・・・何やら顔が映ってる・・・

 

 

いや、私キャッスルの顔なのだが、おかしい。 顔じゃなくて色がね。

怖いよ。 ホラーだよ。 子供は泣くよ。

 

 でも、とりあえずカメラから取得した画像が液晶ディスプレイに出力されたことは確かだ。

このプログラムをベースにいろいろいじって改良していこうと思う。