PIC32MX370F512 OV7670カメラ画像表示

# PIC32MX OV7670カメラ　リアルタイム動画表示

随時、更新予定

:::note warn
24.11.11 ピン配表訂正
:::

<iframe width="560" height="315" src="https://www.youtube.com/embed/RYR613TwfzY?si=FZHPbVEYbRF2fQPs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

O

<img width="300" alt="IMG_5053.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/2031afff-7263-3892-cba9-c613b9370155.jpeg">


<img width="400" alt="IMG_5055.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/30a3683e-3ca5-937e-7938-d11cedb0c7d7.jpeg">

左：OV7670カメラ基板（コネクタ基板）
右：２０Mhzクロック出力回路　74HC04と２０Mhzのセラロックを使用して、カメラに入力。PIC32MXのREFCLKOを使用していたが、高速になると、出力が安定しなかったため。


![IMG_5056.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/f56f8623-99f1-787d-3f67-a8d2ee7aac1e.jpeg)

液晶の大きさは、QQVGA　１２０×１６０ピクセル

# 基本配線図

![pin配改.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/73a5fb66-03d0-0803-5091-cbcd5c81c2b3.png)


# OV7670とPIC32MXの接続。
![簡易配線図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/46beb639-fda1-d8c5-595d-62a248fc2469.jpeg)


# プログラム構成の概略
![プログラムブロック図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/9d40ead6-9701-8290-2721-f01a5ee866ed.jpeg)

カメラから3本の割り込み線が出力されます。垂直同期（行出力）、水平同期(ピクセル同期)、ページ同期。この三本の割り込みを、PIC32MXの外部割込みで取り込みます。PIC32MXのシステムクロックSYSCLKは96Mhzです。残像が残らない程度の速度で画像データを取り込むためには、DMAが必要です。ピクセル同期受信で取り込むデータをバッファに転送するためのDMA。ピクセルデータが行になったときに、行データをSPIを通じて、TFT液晶に転送するDMA、この２つのDMAを使用する必要があります。


# コード
```main.c


// PIC32MX370F512H Configuration Bit Settings

// 'C' source line config statements

// DEVCFG3
#pragma config USERID = 0xFFFF          // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config FSRSSEL = PRIORITY_7     // Shadow Register Set Priority Select (SRS Priority 7)
#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2// PLL Input Divider (1x Divider)
#pragma config FPLLMUL = MUL_24         // PLL Multiplier (20x Multiplier)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)

// DEVCFG1
#pragma config FNOSC = FRCPLL           // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF               // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF            // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECMD           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Disabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config DEBUG = OFF              // Background Debugger Enable (Debugger is Disabled)
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.



#include <xc.h>
#include <stdio.h>

#include <cp0defs.h> 
#include <sys/attribs.h>
#include "peripheral.h"
#include "PIC32_I2C1driver.h"
#include "I2C_LCD.h"
#include "PIC32_SPI2.h"
#include "ds_MCP23S17.h"
#include "ds_ST7735S.h"
#include "PIC32_Graphics.h"
#include "PIC32_I2C2SCCB.h"
#include "OV7670_arCode.h"
#include "OV7670Camera.h"


void portInit(void)
{
    TRISB=0x0000;
    TRISC=0x0000;
    TRISD=0x0000;
    TRISE=0x0000;
    TRISF=0x0000;
    TRISG=0x0000;
    
    ANSELB=0x0000;
    ANSELC=0x0000;
    ANSELD=0x0000;
    ANSELE=0x0000;
    ANSELF=0x0000;
    ANSELG=0x0000;
    
    PORTB=0x0000;
    PORTC=0x0000;
    PORTD=0x0000;
    PORTE=0x0000;
    PORTF=0x0000;
    PORTG=0x0000;
}


void main(void) 
{
    uint8_t val8;
    int i,j;
    int k;
    uint32_t address;
    unsigned int tmp_CP0_Status; // Temporary register for CP0 reg storing 
    
    //oscillator init---------------------------------
    SYSKEY = 0x0;           // ensure OSCCON is locked
    SYSKEY = 0xAA996655;    // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA;    // Write Key2 to SYSKEY
    //PLL Output Divisor bits
    OSCCONbits.PLLODIV=0b000;   //000 = PLL output divided by 1
    //PeripheralBusClock diviser.
    OSCCONbits.PBDIV=0b000;  //SYSCLK divided by1
    //OSCCONbits.PLLMULT = 0b000;
    //Reference clock out　カメラに供給するクロック
    
    //セラロック＋74HC04　20Mhzを使用。
//#define referenceCLK
#ifdef referenceCLK
    RPD9Rbits.RPD9R = 0b0011; //RD9:REFCLKO
    REFOCONbits.RODIV=2; 
    REFOTRIMbits.ROTRIM = 0x0;//96Mhz/(2*2)Mhz=24Mhz
    //実際は、リファレンスクロックの波形が歪んで12Mhzに低下する。
    //REFOTRIMbits.ROTRIM = 0x100;//96Mhz/(2*2.5)=19.2Mhz
    REFOCONbits.OE=1;
    REFOCONbits.ON=1;
    while(REFOCONbits.DIVSWEN);
#endif
    SYSKEY = 0x0;           // ensure OSCCON is locked
    
   
    //port init---------------------------------------
    portInit();//汎用ポート初期化
    
    externalInputInit();//外部入力割込み初期化
    //peripheral initializing-------------------------
    //timer1Init();
    timer2Init();//DMA2トリガーとして使用。
    usartInit();//シリアル通信初期化
    __delay_ms(10);//これを入れないとazが出力されない。
    //putchar('a');putchar('z');
    I2C1_Init();//I2C1モジュール初期化
    LCD_Init(LcdDeviceAdd);
    //I2C1BRG=0x003D;//600khz Fp=80Mhz
    LCD_Printf(LcdDeviceAdd,"PIC32MX370F512F",15,0x80);
    //Camera--------------------------------------------
    I2C2_Init();//SCCB for OV7670
    camInit();//カメラ初期化
    cammode_select();//カメラ　画面大きさ、RGB565、クロック処理
    
    //Camera initialized values confirming.
    printf("AD: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F\r00:");
    for(i=0x00; i<0xCA; i++)
    {   
        val8=I2C2_b1Read(OV7670deviceAdd,i,true);
        printf(" %02X",val8);
        if((i+1)%16==0 && i!=0) 
        {
            printf("\r%02X:",i+1);
        }
    }
    printf("\r");
  
    //Camera user value initializing--------------------
    OV7670_Init();
    
    //ST7735液晶初期化-----------------------------------
    Spi2Init();
    ST7735S_Init();
    __delay_ms(100);
    ST7735S_PaintALL(0xFF,0xFF,0xFF);
    
    //DMA初期化--------------------------------------
    DMA2Init();//for TFT LCD with SPI
    DMA1Init();//for pixceldata
    
    //ST7735液晶用RAM画面クリア（灰色）
    k=0;
    for(i=0; i<128; i++)
        for(j=0; j<160; j++)
        {
            sprite1[k++]=0x70;
            sprite1[k++]=0x70;
            sprite1[k++]=0x70;
        }
    
    
    //interrupt initializing-------------------------
    //printf("\nPIC32MX370F512HT\n");
    
    //割り込み関連初期化
    address=_CP0_GET_EBASE();//例外ベクタアドレス
    printf("EBASE=%lx\n",address);
    INTCONbits.MVEC=1;
    tmp_CP0_Status=_CP0_GET_STATUS();
    tmp_CP0_Status|=0x00000001;//CP0.STATUS.IE=1で割り込み許可
    _CP0_SET_STATUS(tmp_CP0_Status);
    // __builtin_enable_interrupts();
   
    
    
    while(1)
    {
        /*if(rxU1.completed)
        {
            rxU1.completed=false;
            printf("%s\r",rxU1.buf);            
            rxU1.length=0;
            IEC1bits.U1RXIE=1;
        }*/
    }
    
    
    return;
}

```

```Peripheral.h


#ifndef PERIPHERAL_H
#define	PERIPHERAL_H

#ifdef	__cplusplus
extern "C" {
#endif
#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <stdio.h>
#include <stdbool.h>
#include <sys/kmem.h>
    
#define SYSCLK      96000000L		// System clock 40Mhz
#define CTCLK		(SYSCLK / 2)    // CoreTimerCLK SystemClock/2
#define CTus 		(CTCLK / 1000000)	// us delay unit Term
#define CTms     	(CTCLK / 1000)	// ms delay unit Term

#define High 1
#define Low  0
    

//USART-----------------------------------    
#define BAUDRATE 115200
#define SET_SPBRG_DATA  (((unsigned int)((SYSCLK/4)/BAUDRATE))-1)
#define SET_SPBRG_DATA1 (((unsigned int)((SYSCLK/16)/BAUDRATE))-1)    

#define RXUSART_BUFFER_SIZE 50
typedef struct
{
    uint8_t buf[RXUSART_BUFFER_SIZE];
    uint8_t length;
    uint8_t completed;
    uint8_t ch;
}_rxUsart;
extern volatile _rxUsart rxU1;

extern void usartInit(void);
extern uint8_t getch(void);
extern void myUsartPrint(uint8_t *txBuf, uint8_t _length);    
    
//Timer-----------------------------------------------
    typedef struct{
        uint32_t cnt;
        bool fg;
        bool fg1;
    }_tm;
extern _tm tm1;
extern void timer1Init(void);
extern void timer2Init(void);

//External Interrupt-----------------------------------
typedef struct{
    bool fg;
}_exINT;

extern _exINT exINT0,exINT1,exINT2; 
void externalInputInit(void);

//Delay------------------------------------------------    
extern void __delay_ms(long _ms);
extern void __delay_us(long _us);
    

//DMA---------------------------------------------------
extern void DMA2Init(void);
extern void DMA1Init(void);
#ifdef	__cplusplus
}
#endif

#endif	/* PERIPHERAL_H */


```

```Peripheral.c
#include "peripheral.h"
#include "PIC32_Graphics.h"

//USART---------------------------------------------------
//USART受信用構造体
volatile _rxUsart rxU1;

/**
 * usart初期化関数
 */
void usartInit(void)
{
    //1.ボーレート設定115200
    U1BRG=SET_SPBRG_DATA1;
    //2.Serial mode setting
    U1RXREG=0x0000;
    U1TXREG=0x0000;
    U1MODEbits.PDSEL=0b00;//8bits no parity
    U1MODEbits.STSEL=1;//1stopbits
    //PPS
    SYSKEY = 0x0; // ensure OSCCON is locked
    SYSKEY = 0xAA996655; // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA; // Write Key2 to SYSKEY

    RPC13Rbits.RPC13R=0b0011; //RPC13:U1TX
    U1RXR=0b0111;             //RPC14:U1RX
    
    SYSKEY = 0x0; // ensure OSCCON is locked
    
    //Rx interrupt
    IFS1bits.U1RXIF=0;
    IPC7bits.U1IP=1;
    IPC7bits.U1IS=1;
    IEC1bits.U1RXIE=1;
    U1STAbits.URXISEL=0b00;//not empty
   
    //IO direction change
    TRISC=0x0000;
    TRISCbits.TRISC14=1; //Input For U1RX.
    
    rxU1.length=0;
    //4.Serial port enabled
    U1STAbits.URXEN=1;
    U1STAbits.UTXEN=1;
    U1MODEbits.ON=1;
}

/**
 * 32-Bit Language Tools Libraries P.38
 * Description: Writes a character to stdout.
 * printf文で使用。
 * @param c 出力１文字
 */
void _mon_putc (char c)
{
    while (U1STAbits.UTXBF); //Wait till transmission is complete
    U1TXREG = c;
}

/**
 * usart 文字入力受信関数
 * @return 受信文字
 */
uint8_t getch(void)
{
    while(!U1STAbits.URXDA)
            return U1RXREG;
}

//タイマー------------------------------------------
_tm tm1;

/**
 *Timer1初期化 
 */
void timer1Init(void)
{
    T1CON=0x00;
    TMR1=0x0000;
    //PR1=0x1388;//PBCLK=40Mhz
    PR1=0x2710;//PBCLK=80Mhz
    T1CONbits.TCKPS=0b01; //1:8
    T1CONbits.ON=1;
    IFS0bits.T1IF=0;
    IPC1bits.T1IP=1;
    IPC1bits.T1IS=0;
    IEC0bits.T1IE=1;
}

//Fpb=80Mhz 0.025us * 2 * 10 = 0.5us
void timer2Init(void)
{
    T2CON=0x00;
    TMR2=0x00;
    PR2=0x000F;
    T2CONbits.T32=0;//16bitsTimer
    T2CONbits.TCKPS=0b001;//1:2 prescale 
    T2CONbits.TCS=0;//internal peripheral clock
    IFS0bits.T2IF=0;
    IPC2bits.T2IP=1;
    IPC2bits.T2IS=0;
    IEC0bits.T2IE=0;
    T2CONbits.ON=0;
}


//Exteranl interrupt---------------------------------
_exINT exINT0,exINT1,exINT2; 
void externalInputInit(void)
{
    //INT0 initialize
    INTCONbits.INT0EP=1;//0:Falling edge 1:Rising edge
    IEC0bits.INT0IE=1;
    IPC0bits.INT0IP=7;
    TRISFbits.TRISF6=1;
    CNPUFbits.CNPUF6=1;
    exINT0.fg=false;
    
    //INT1,2 initilize
    //PPS
    INT1Rbits.INT1R = 0b0000;//INT1:RD1
    INT2Rbits.INT2R = 0b0100;//INT2:RD4
    INTCONbits.INT1EP = 1;//0:Falling edge 1:Rising edge
    INTCONbits.INT2EP = 1;//0:Falling edge 1:Rising edge
    IEC0bits.INT1IE =1;
    IEC0bits.INT2IE =1;
    IPC1bits.INT1IP = 7;
    IPC2bits.INT2IP = 7;
    TRISDbits.TRISD1=1;
    TRISDbits.TRISD4=1;
    CNPUFbits.CNPUF1=1;
    CNPUFbits.CNPUF4=1;
    exINT1.fg=false;
    exINT2.fg=false;
    
    IFS0bits.INT0IF=0;
    IFS0bits.INT1IF=0;
    IFS0bits.INT2IF=0;
}

//ディレイ--------------------------------------------
/**
 * __delay_ms
 * @param _ms
 */
void __delay_ms(long _ms)
{
    long count;
    count=_ms*CTms;
    _CP0_SET_COUNT(0);
    while(_CP0_GET_COUNT()<=count);
}

/**
 * __delay_us
 * @param _us
 */
void __delay_us(long _us)
{
    long count;
    count=_us*CTus;
    _CP0_SET_COUNT(0);
    while(_CP0_GET_COUNT()<=count);
}

//DMA2-------------------------------------------------
//sprite1からSPI2へ転送
void DMA2Init(void)
{
    IEC2bits.DMA2IE = 0;   // 設定のためDMA2を一時停止させる
   
    DCH2CON = 0;
    DCH2ECON = 0;
    DCH2INT = 0;

    DCH2CONbits.CHPRI = 3;              // DMAチャネルの優先度(3)
    DCH2ECONbits.CHSIRQ = _TIMER_2_IRQ;   // DMAを開始する割り込み番号
    DCH2ECONbits.SIRQEN = 1;            // 割り込みによる転送を有効にする
    DCH2INTbits.CHBCIE = 1;             // Channel Block Transfer Complete Interrupt Flag bit
    
   
    
    DCH2SSA = KVA_TO_PA(&sprite1);
    //DCH2SSIZ = 128*160*3;
    DCH2SSIZ = 160*2;
    DCH2DSA = KVA_TO_PA(&SPI2BUF);
    DCH2DSIZ = 1;
    DCH2CSIZ = 1;
    
    IFS2bits.DMA2IF = 0;   // 割り込みフラグのクリア
    IPC11bits.DMA2IP = 7;  // 割り込み優先度
    IPC11bits.DMA2IS = 3;  // 副割り込み優先度
    IEC2bits.DMA2IE = 1;   // DMA2割り込みを有効にする
    DCH2CONbits.CHEN = 1;               // DMA1を使用する
    DMACONbits.ON = 1;     // DMAモジュールを有効にする
}

//DMA1-------------------------------------------------
//PORTEからsprite1へ転送
void DMA1Init(void)
{
    IEC2bits.DMA1IE = 0;   // 設定のためDMA2を一時停止させる
   
    DCH1CON = 0;
    DCH1ECON = 0;
    DCH1INT = 0;

    DCH1CONbits.CHPRI = 3;              // DMAチャネルの優先度(3)
    DCH1ECONbits.CHSIRQ = _EXTERNAL_1_IRQ;   // DMAを開始する割り込み番号
    DCH1ECONbits.SIRQEN = 1;            // 割り込みによる転送を有効にする
    DCH1INTbits.CHDDIE = 1;             // Channel Block Transfer Complete Interrupt Flag bit
    
   
    
    DCH1SSA = KVA_TO_PA(&PORTE);
    DCH1SSIZ = 1;
    DCH1DSA = KVA_TO_PA(&sprite1);
    DCH1DSIZ = 160*2;
    DCH1CSIZ = 1;
    
    IFS2bits.DMA1IF = 0;   // 割り込みフラグのクリア
    IPC10bits.DMA1IP = 7;  // 割り込み優先度
    IPC10bits.DMA1IS = 3;  // 副割り込み優先度
    IEC2bits.DMA1IE = 1;   // DMA2割り込みを有効にする
    DCH1CONbits.CHEN = 1;               // DMA1を使用する
    DMACONbits.ON = 1;     // DMAモジュールを有効にする
}
```

```interrupt.h

#ifndef INTERRUPT_H
#define	INTERRUPT_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <sys/attribs.h>
#include "peripheral.h"
     
extern void __ISR(_TIMER_1_VECTOR) ISR_Timer1(void);
extern void __ISR(_UART_1_VECTOR) ISR_UART1(void);
extern void __ISR(_EXTERNAL_2_VECTOR, IPL7AUTO) ISR_INT2(void);
extern void __ISR(_EXTERNAL_0_VECTOR, IPL7AUTO) ISR_INT0(void);
extern void __ISR(_EXTERNAL_1_VECTOR, IPL7AUTO) ISR_INT1(void);
extern void __ISR(_DMA2_VECTOR, IPL7AUTO) ISR_Dma2(void);
extern void __ISR(_DMA1_VECTOR, IPL7AUTO) ISR_Dma1(void);
#ifdef	__cplusplus
}
#endif

#endif	/* INTERRUPT_H */


```

```interrupt.c
#include <proc/p32mx370f512h.h>

#include "interrupt.h"
#include "PIC32_Graphics.h"
#include "OV7670Camera.h"


//Timer1 interrupt
void __ISR(_TIMER_1_VECTOR,IPL1AUTO) ISR_Timer1(void)
{
    IFS0bits.T1IF=0;
    tm1.cnt++;
    if(tm1.cnt%5==0)
    {
        tm1.fg1=true;
    }
    if(tm1.cnt==500)
    {
        tm1.cnt=0;
        tm1.fg=true;
        IEC0bits.T1IE=0;
        //LATBbits.LATB0=~LATBbits.LATB0;
    } 
}

//USART1 RX interrupt
void __ISR(_UART_1_VECTOR,IPL1AUTO) ISR_UART1(void)
{
    if( IFS1bits.U1RXIF==1)
    {
        IFS1bits.U1RXIF=0;
        if(U1STAbits.URXDA)
        {
            do{
                rxU1.ch=U1RXREG;
                rxU1.buf[rxU1.length]=rxU1.ch;
                rxU1.length++;
                if(rxU1.length>=RXUSART_BUFFER_SIZE)
                {
                    rxU1.length=0;
                }
            }while(U1STAbits.URXDA);  
            if(rxU1.ch==0x0a && rxU1.length>=3)//0x0a:'\n'
            {
                //rxUsart.buf[rxUsart.length-2]='\0';//\a\n終端文字FromPC
                rxU1.buf[rxU1.length-2]=0x00;//\a\n終端文字FromPC
                rxU1.completed=true;  
                IEC1bits.U1RXIE=0;
            } 
        }
    }
}


//VSYNC割込み INT2:RD4
void __ISR(_EXTERNAL_2_VECTOR, IPL7AUTO) ISR_INT2(void)
{
    LATBbits.LATB2 = ~LATBbits.LATB2;
    IFS0bits.INT2IF=0;
    OV7670.LineCounter=0;
    OV7670.HpixCounter=0;
    
}

//HREF割込み　INT0:RF6
void __ISR(_EXTERNAL_0_VECTOR, IPL7AUTO) ISR_INT0(void)
{
    IFS0bits.INT0IF=0;
    if(INTCONbits.INT0EP==1)
    {//立上り割込み処理
        LATBbits.LATB0=1;
        INTCONbits.INT0EP=0;//立下り待ちにする。
        
        OV7670.LineCounter++;
        if(OV7670.LineCounter==120)
        {
            OV7670.LineCounter=0;
        }
        //printf("%d ", OV7670.HpixCounter);
        OV7670.HpixCounter=0;
    }else
    {//立下り割込み処理
        INTCONbits.INT0EP=1;//立上り待ちにする。
        //SPIでTFTに転送するフラグを立てる。
        //OV7670.fg_TFT_Send = true;
        //pushSprite();
        LATBbits.LATB0=0;
    }
    
    
}

//PCLK割込み INT1:RD1
void __ISR(_EXTERNAL_1_VECTOR, IPL7AUTO) ISR_INT1(void)
{
    IFS0bits.INT1IF=0;
    LATBbits.LATB1=~LATBbits.LATB1;
    //OV7670.portBval = (uint8_t)PORTE;
    //sprite1[OV7670.HpixCounter++]=OV7670.portBval;
    //sprite1[OV7670.HpixCounter++]=PORTE;
}

//DMA2
//トリガー:Timer2
//from sprite1 to SPI2BUF
//sprite1 size:160*2
//SPI2BUF size:1
void __ISR(_DMA2_VECTOR, IPL7AUTO) ISR_Dma2(void)
{     
    IFS2bits.DMA2IF = 0;        // DMA1割り込みフラグのクリア
    if(DCH2INTbits.CHBCIF == 1)
    {
        SPI2_Stop();
        T2CONbits.ON=0;
        //LATBbits.LATB1=~LATBbits.LATB1;
        DCH2SSA = KVA_TO_PA(&sprite1);
        
        DCH2CONbits.CHEN = 1;   // DMA1を有効にする
        
        DCH2INTbits.CHBCIF = 0; // ブロック終了割り込みフラグのクリア
        
        DCH2ECONbits.SIRQEN = 1;
    }
    
}

//DMA1
//トリガー:外部割込み１ INT1
//from PORTE(size 1)
//to sprite1(size160*2)
void __ISR(_DMA1_VECTOR, IPL7AUTO) ISR_Dma1(void)
{
    IFS2bits.DMA1IF=0;
    if(DCH1INTbits.CHDDIF==1)
    {
        DCH1INTbits.CHDDIF=0;
        pushSprite();
        DCH1DSA = KVA_TO_PA(&sprite1);
        DCH1CONbits.CHEN=1;
    }
}
```

```I2C2_SCCB.h


#ifndef PIC32_I2C2_H
#define	PIC32_I2C2_H

#ifdef	__cplusplus
extern "C" {
#endif
   
#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <stdio.h>
#include <stdbool.h>
//デバイスアドレス
#define MCP4726DeviceAdd 0xC0
    
#define I2C2_Ack   0//SSP1CON2.ACKDT master:receive mode
#define I2C2_NoAck 1//SSP1CON2.ACKDT master:receive mode    
    
#define I2C2_SCL_PIN PORTFbits.RF5 
#define I2C2_SDA_PIN PORTFbits.RF4
    
extern void I2C2_Init(void);
extern void I2C2_Reset(void);
extern bool I2C2_CheckIdle(void);
extern bool I2C2_ClearIF(bool _sccb);
extern bool I2C2_Start(bool _sccb);
extern bool I2C2_ReStart(void);
extern bool I2C2_Stop(bool _sccb);
extern bool I2C2_Tx_Buffer_Write(uint8_t  _data);
extern uint8_t I2C2_Rx_Buffer_Read(void);
extern bool I2C2_Wait_Ack(bool _sccb);
extern bool I2C2_Send_Ack(uint8_t _Ack_Nack);


extern uint8_t I2C2_DataBuffer[10];
//------------------------------------------------------------------------
extern uint8_t I2C2_b1Write(uint8_t _device_add, uint8_t _data,bool _sccb);
extern uint8_t I2C2_b2Write(uint8_t _device_add, uint8_t _data1, uint8_t _data2,bool _sccb);
extern bool I2C2_bnWrite(uint8_t _device_add, uint8_t *_data, uint8_t _len,bool _sccb);
extern uint8_t I2C2_b1Read(uint8_t _device_add, uint8_t _data1,bool _sccb);
extern bool I2C2_bnRead(uint8_t _device_add, uint8_t _data1,uint8_t _len,bool _sccb);
#ifdef	__cplusplus
}
#endif

#endif	/* PIC32_I2C2 */


```

```I2C2_SCCB.c

//
//220812 b1Read最後のNack修正。

#include "PIC32_I2C2SCCB.h"
#include "peripheral.h"

uint8_t I2C2_DataBuffer[10];

void I2C2_Init(void)
{
    unsigned int i;
   
    I2C2CON=0x0000;
    
    //I2C2BRG=0x002F;//400kHz Fp=40Mhz
    I2C2BRG=0x0189;//100khz Fp=80Mhz
    I2C2CONbits.DISSLW=1;//errata
    I2C2CONbits.STREN=1;
    I2C2CONbits.ON=1;
   
    IFS1bits.I2C2MIF=0;
    IEC1bits.I2C2MIE=0;
    IFS1bits.I2C2SIF=0;
    IEC1bits.I2C2SIE=0;
}

void I2C2_Reset(void)
{
    unsigned int buf;
    I2C2CONbits.I2CEN=0;
    buf=TRISB;
    buf|=0x0000;
    I2C2_SCL_PIN=0;
    __delay_us(10);
    I2C2_SCL_PIN=1;
    __delay_us(10);
    I2C2_SCL_PIN=0;
    __delay_us(10);
    I2C2_SCL_PIN=1;
    __delay_us(10);
}

bool I2C2_CheckIdle(void)
{
    signed int i;
    unsigned int buf;
   
    for(i=0x7FFF; i; i--)
    {
        buf=I2C2CON;
        //buf&=0x44DB;
        buf&=0x001F;
        if(!buf)
            return true;
    }
    return false;
}

bool I2C2_ClearIF(bool _sccb)
{
    signed int i;
    for(i=0x3FFF; i; i--)
    {
        if(IFS1bits.I2C2MIF)
        {
            IFS1bits.I2C2MIF=0;
            return true;
        }
    }
    return false;
}

bool I2C2_Start(bool _sccb)
{
    signed int i;

    for(i=0x3FFF; i; i--)
    {
        if(I2C2_CheckIdle())
        {
            I2C2CONbits.SEN=1;
            if(I2C2_ClearIF(_sccb));
                return true;
        }
    }
    return false;
}

bool I2C2_ReStart(void)
{
     //restart
    signed int i;
    for(i=0x3FFF; i; i--)
    {
        if(I2C2_CheckIdle())
        {
            I2C2CONbits.RSEN=1;
            return true;
        }
    }
    return false;
}

bool I2C2_Stop(bool _sccb)
{
    signed int i;
    for(i=0x3FFF; i; i--)
    {
        if(I2C2_CheckIdle())
        {
            I2C2CONbits.PEN=1;
            while(I2C2CONbits.PEN);
            if(I2C2_ClearIF(_sccb))
                return true;
        }
    }
    return false;
    
}

//I2C2 transmit register write
//TBS: 0:empty 1:I2C2TRN full
bool I2C2_Tx_Buffer_Write(uint8_t _data)
{
    signed int i,j;
    
    if(!I2C2_CheckIdle())return false;
    I2C2TRN=_data;
    for(i=0x7FFF; i; i--)
    {
        if(!I2C2STATbits.TBF)
        {
            return true;
        }
    }
    return false;
}

uint8_t I2C2_Rx_Buffer_Read(void)
{
    uint8_t ret,cnt;
    ret=0xFF;
    cnt=0;
    if(!I2C2_CheckIdle())return false;
    I2C2CONbits.RCEN=1;
    while(!I2C2STATbits.RBF){
         __delay_us(3);
        cnt++;
        if(cnt==200)return false;
    }; 
    if(!I2C2_CheckIdle())return false;
    ret = I2C2RCV;
    return ret;
}

//ACKSTAT 0:ACK 1:NACK
bool I2C2_Wait_Ack(bool _sccb)
{
    signed int i;
    
    if(_sccb)return true;
    
    for(i=0x7FFF; i; i--)
    {
        if(!I2C2STATbits.ACKSTAT)
            return true;
    }
    return false;
}

bool I2C2_Send_Ack(uint8_t _Ack_Nack)
{
    if(!I2C2_CheckIdle())return false;
    I2C2CONbits.ACKDT=_Ack_Nack;
    I2C2CONbits.ACKEN=1;   
    return true;
}
//------------------------------------------------------------------------
uint8_t I2C2_b1Write(uint8_t _device_add, uint8_t _data,bool _sccb)
{  
    //start condition
    I2C2_Start(_sccb);
    //send device address
    I2C2_Tx_Buffer_Write(_device_add);
    if(!I2C2_Wait_Ack(_sccb))
        return 0xE1;
    if(!I2C2_ClearIF(_sccb))
        return 0xE2;
    //send data
    I2C2_Tx_Buffer_Write(_data);
    if(!I2C2_Wait_Ack(_sccb))
        return 0xE3;
    if(!I2C2_ClearIF(_sccb))
        return 0xE4;
    //Stop condition
    I2C2_Stop(_sccb);
    return true;
}

bool I2C2_bnWrite(uint8_t _device_add, uint8_t *_data, uint8_t _len, bool _sccb)
{
    uint8_t buf;
    //start condition
    I2C2_Start(_sccb);
    //send device address
    I2C2_Tx_Buffer_Write(_device_add);
     if(!I2C2_Wait_Ack(_sccb))
        return false;
    if(!I2C2_ClearIF(_sccb))
        return false;
   
    //send data
    do{
        buf=*_data;
        I2C2_Tx_Buffer_Write(buf);
        if(!I2C2_Wait_Ack(_sccb))
            return false;
        if(!I2C2_ClearIF(_sccb))
        return false;
        _data++;
        _len--;
    }while(_len!=0);
    //Stop condition
    I2C2_Stop(_sccb);
    return true;
}

uint8_t I2C2_b2Write(uint8_t _device_add, uint8_t _data1, uint8_t _data2, bool _sccb)
{
    //start condition
    I2C2_Start(_sccb);
    //send device address-----------------
    I2C2_Tx_Buffer_Write(_device_add);
    I2C2_Send_Ack(I2C2_Ack);
    if(!I2C2_ClearIF(_sccb))
    {
        return 0x42;
    }
    //send data1------------------------
    I2C2_Tx_Buffer_Write(_data1);
    I2C2_Send_Ack(I2C2_Ack);
    if(!I2C2_ClearIF(_sccb))
        return 0x44;
        //send data
    //send data2------------------------
    I2C2_Tx_Buffer_Write(_data2);
    I2C2_Send_Ack(I2C2_Ack);
    if(!I2C2_ClearIF(_sccb))
    {
        return 0x46;
    }
    //Stop condition
    I2C2_Stop(_sccb);
    if(_sccb)__delay_ms(15);
    return true;
}



uint8_t I2C2_b1Read(uint8_t _device_add, uint8_t _data1, bool _sccb)
{
    uint8_t ret;
    //Start Condition
    I2C2_Start(_sccb);
     //send device address
    ret=I2C2_Tx_Buffer_Write(_device_add);
    I2C2_Send_Ack(I2C2_Ack);
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA1;
    }
    
    //send data
    I2C2_Tx_Buffer_Write(_data1);
    I2C2_Send_Ack(I2C2_Ack);
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA3;
    }
    //Stop Condition
    ret=I2C2_Stop(_sccb);
    //restart
    
    I2C2_Start(_sccb);
      //send device address
    I2C2_Tx_Buffer_Write(_device_add|0x01);
    I2C2_Send_Ack(I2C2_Ack);
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA6;
    }
    //recieve data
    ret=I2C2_Rx_Buffer_Read();
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA7;
    }
    //send Nack
    I2C2_Send_Ack(I2C2_NoAck);
    if(!I2C2_ClearIF(true))
    {
        return 0xA2;
    }
    //Stop Condition
    I2C2_Stop(_sccb);
    
    
    return ret;
}

bool I2C2_bnRead(uint8_t _device_add, uint8_t _data1,uint8_t _len, bool _sccb)
{
    uint8_t index=0;
     //Start Condition
    I2C2_Start(_sccb);
     //send device address
    I2C2_Tx_Buffer_Write(_device_add);
    if(!I2C2_Wait_Ack(_sccb))
    {
        return 0xA0;
    }
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA1;
    }
    
    //send data
    I2C2_Tx_Buffer_Write(_data1);
    if(!I2C2_Wait_Ack(_sccb))
    {
        return 0xA2;
    }
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA3;
    }
    //restart
    I2C2_ReStart();
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA4;
    }
      //send device address
    I2C2_Tx_Buffer_Write(_device_add|0x01);
    if(!I2C2_Wait_Ack(_sccb))
    {
        return 0xA5;
    }
    if(!I2C2_ClearIF(_sccb))
    {
        return 0xA6;
    }
    //recieve data
    do{
        I2C2_DataBuffer[index++]=I2C2_Rx_Buffer_Read();
        if(!I2C2_ClearIF(_sccb))
        {
            return 0xA7;
        }
        if(_len!=1)
        {
            I2C2_Send_Ack(I2C2_Ack);
        }
        _len--;
    }while(_len!=0);
    
    //send Nack
    I2C2_Send_Ack(I2C2_NoAck);
 
    I2C2_Stop(_sccb);
    return true;
}
  


```

```SPI2.h

#ifndef DSSSP2_H
#define	DSSSP2_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <stdio.h>
#include <stdbool.h>
#include "peripheral.h"    
    
#define Low 0
#define High 1    
    
#define SPI2_CS LATBbits.LATB5
    
typedef struct{
    uint8_t val;
    bool error;
}_SPI_RD;   

extern _SPI_RD SPI_RD;    
extern void Spi2Init(void);
extern void SPI2_Start(void);
extern uint8_t SPI2_Write(unsigned char _data);
extern bool SPI2_Write3byte(unsigned char _data0,unsigned char _data1,unsigned char _data2);

extern _SPI_RD SPI2_Read(void);
extern void SPI2_Stop(void);


/*-----------------------------------*/
//MCP23S08 I/O expander
/*-----------------------------------*/
#define MCP23S08_Device1Add 0x40
#define MCP23S08_Device2Add 0x42
#define MCP23S_R 1
#define MCP23S_W 0



typedef enum 
{
    IODIR=0x00,
    IPOL,
    GPINTEN,
    DEFVAL,
    INTCN,
    IOCON,
    GPPU,
    mINTF,
    INTCAP,
    GPIO,
    OLAT=0x0A
}_reg;

extern unsigned char  reg_value[10];

extern bool MCP23S_Init(uint8_t _device_add);
extern bool MCP23S_SendOPcode(uint8_t _device_add, uint8_t _reg_add, uint8_t RW);
extern bool MCP23S_WriteReg(uint8_t _device_add,uint8_t _reg_add, uint8_t _data);
extern bool MCP23S_b2Write(uint8_t _device_add, uint8_t _data1, uint8_t _data2);
extern uint8_t MCP23S_b1ReadReg(uint8_t _device_add, uint8_t _reg_add);
#ifdef	__cplusplus
}
#endif

#endif	/* SSP1_H */


```

```SPI2.c
#include "PIC32_SPI2.h"


_SPI_RD SPI_RD;
//SPI2 for TFT液晶ST7735
void Spi2Init(void)
{
    //1.using Interrupt
    IFS1bits.SPI2EIF=0;
    IEC1bits.SPI2EIE=0;
    //2.Master Mode
    SPI2CONbits.DISSDI=0;
    SPI2CONbits.DISSDO=0;
    SPI2CONbits.MODE16=0;
    SPI2CONbits.MODE32=0;
    SPI2CONbits.SMP=1;
    SPI2CONbits.CKE=1;
    SPI2CONbits.CKP=0;
    SPI2CONbits.MSTEN=1;//master mode
    SPI2CON2bits.AUDEN=0;
    //3.SPI baudrate 
    //SPI2BRG=255;
    //SPI2BRG=1;//24Mhz Fpb=96Mhz
    SPI2BRG=0;//40Mhz Fpb=96Mhz
    SPI2STATbits.SPIROV=0;
    SPI2CON2=0x0000;
    SPI2CONbits.ENHBUF=0;//FIFObuffer no use:0    
    //5.Port pin 
    
    //SDO2 RD11
    RPD11Rbits.RPD11R = 0b0110;
    //SDI2 RD3
    SDI2R = 0b0000;//RPD3
    
    TRISD|=0x0008; //RD3
    //4.SPI enable
    SPI2CONbits.ON=1;//1:Enable SPI
}

void SPI2_Start(void)
{
    SPI2_CS=Low;
}

uint8_t SPI2_Write(unsigned char _data)
{
   int  i;
    unsigned char buf;
    i=0;
    buf=SPI2BUF;
    for(i=0x7FFF; i; i--)
    {
        if(!SPI2STATbits.SPITBF)
        {
            break;
        }
    }
    SPI2BUF=_data;
    for(i=0x7FFF; i; i--)
    {
        if(!SPI2STATbits.SPITBF)
        {
            break;
        }
    }
    for(i=0x7FFF; i; i--)
    {
        if(!SPI2STATbits.SPIBUSY)
        {
            return true;
        }
    }
    return false;
}

bool SPI2_Write3byte(unsigned char _data0,unsigned char _data1,unsigned char _data2)
{
   int  i,j;
    unsigned char buf;
    for(j=0; j<3; j++)
    {
        buf=SPI2BUF;
        for(i=0x7FFF; i; i--)
        {
            if(!SPI2STATbits.SPITBF)
            {
                break;
            }
        }
        if(j==0)
            SPI2BUF=_data0;
        if(j==1)
            SPI2BUF=_data1;
        if(j==2)
            SPI2BUF=_data2;
        for(i=0x7FFF; i; i--)
        {
            if(!SPI2STATbits.SPITBF)
            {
                break;
            }
        }
        for(i=0x7FFF; i; i--)
        {
            if(IFS1bits.SPI1EIF)
            {
                IFS1bits.SPI1EIF=0;
                break;
            }
        }
    }
    return true;
}



_SPI_RD SPI2_Read(void)
{
    signed int i;
    
    SPI_RD.error=true;
    SPI_RD.val=0xFC;
    for(i=0x7FFF; i; i--)
    {
        if(SPI2STATbits.SPIRBF)
        {
            SPI_RD.val=SPI2BUF;
            SPI_RD.error=false;
            break;
        }
    }    
    return SPI_RD;
}

void SPI2_Stop(void)
{
    unsigned char buf;
    buf=SPI2BUF;
    SPI2_CS=High;
    __delay_us(10);
}


/*-----------------------------------*/
//MCP23S08 I/O expander
/*-----------------------------------*/
_reg MCP23S08reg;
unsigned char  reg_value[10]={0x00,0x00,0x00,0x00,0x18,
0xFF,0x00,0x00,0x00,0x00};
_SPI_RD SPI_RD;

bool MCP23S_Init(uint8_t _device_add)
{
    bool ret;
    ret=MCP23S_WriteReg(_device_add,IODIR,0x00);
    if(!ret) return 0xB1;
    __delay_ms(1);
    ret=MCP23S_WriteReg(_device_add,IOCON,0x38);
    if(!ret) return 0xB2;
    return true;
}


bool MCP23S_SendOPcode(uint8_t _device_add, uint8_t _reg_add, uint8_t RW)
{
    bool ret=false;
   
    ret=SPI2_Write(_device_add|RW);
    if(!ret)
    {
        return false;
    }
    ret=SPI2_Write(_reg_add);
    if(!ret)
    {
        return false;
    }
    return ret;
}

bool MCP23S_WriteReg(uint8_t _device_add,uint8_t _reg_add, uint8_t _data)
{
    bool ret=false;
    SPI2_Start();
    ret=MCP23S_SendOPcode(_device_add, _reg_add, MCP23S_W);
    if(ret!=true)
        return 0xF1;
    ret=SPI2_Write(_data);
    if(ret!=true)
        return 0xF2;
    SPI2_Stop();
    return ret;
}        

bool MCP23S_b2Write(uint8_t _device_add, uint8_t _data1, uint8_t _data2)
{
    bool ret=false;
    SPI2_Start();
    ret=SPI2_Write(_device_add|MCP23S_W);
    if(ret!=true)
        return 0xF1;
    ret=SPI2_Write(_data1);
    if(ret!=true)
        return 0xF2;
    ret=SPI2_Write(_data2);
    if(ret!=true)
        return 0xF3;
    SPI2_Stop();
    return ret;
}

uint8_t MCP23S_b1ReadReg(uint8_t _device_add, uint8_t _reg_add)
{
    bool ret;
    _SPI_RD rdRet;
    SPI2_Start();
    
    ret=SPI2_Write(_device_add|MCP23S_R);
    if(!ret)
    {
        return false;
    }
    ret=SPI2_Write(_reg_add);
    if(!ret)
    {
        return false;
    }
    SPI2_Write(0xFF);
    rdRet=SPI2_Read();
    
    SPI2_Stop();
    
     
    if(rdRet.error)
    {
        return rdRet.val=0xFE;
    }
    return rdRet.val;
}
```

```ST7735S.h
/* 
 * File:   ST7735S.h
 * Author: h
 *
 * Created on 2021/06/20, 15:37
 * 21.08.11　1216フォント追加
 * 21.08.27　dsPIC用
 */

#ifndef ST7735S_H
#define	ST7735S_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <stdio.h>
#include <stdbool.h>
#include "peripheral.h"    

#define line0 115
#define line1 103
#define line2 91
#define line3 79
#define line4 67
#define line5 55
#define line6 43
#define line7 31
#define line8 19
#define line9 12
#define line10 0    
    
    
#define ST7735_CM 0
#define ST7735_DT 1
 
//#define backColor_White
#define backColor_Black
#ifdef backColor_Black
#define backColor_R 0xFC
#define backColor_G 0xFC    
#define backColor_B 0xFC    
#endif
#ifdef backColor_White
#define backColor_R 0x10
#define backColor_G 0x10    
#define backColor_B 0xFC    
#endif


    
#define char8Y_R 0x40
#define char8Y_G 0x30
#define char8Y_B 0x00   
    
#define char10Y_R 0xFC
#define char10Y_G 0x30
#define char10Y_B 0x00  
    
#define char12Y_R 0xFC
#define char12Y_G 0x00
#define char12Y_B 0x00    

#define char16Y_R 0xFC
#define char16Y_G 0x00
#define char16Y_B 0x00        
    
#define char88Offset 0x60
#define char88OffsetNumber 2       
#define char1010OffsetNumber 2
#define char1010OffsetAZ    0x34    
#define char1216OffsetNumber 3
#define char1216OffsetAZ 0x33
    
extern const uint8_t char8Set[38][8];     
extern volatile uint8_t *psv_pt;
extern  const uint8_t char10Set[39][20]; 
extern  const uint8_t char12Set[10][24]; 
extern  const uint8_t char1216Set[41][24];
extern  const uint8_t char1616Set[6][32];

typedef struct{
    uint8_t cnt;
}_ST7735;
extern volatile _ST7735 ST7735;

#define ST7735_A0 LATBbits.LATB3

 
    
extern void ST7735S_Init(void);
extern void ST7735S_Write(uint8_t _CD, uint8_t _data);
extern void ST7735S_AddSet(uint8_t _xs,uint8_t _xe, uint8_t _ys,uint8_t _ye);
extern void ST7735S_WriteChar8X(const uint8_t* _ch);
extern void ST7735S_WriteChar8Y(const uint8_t* _ch,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_WriteChar10Y(const uint8_t* _ch, uint8_t _R, uint8_t _G, uint8_t _B);
extern void ST7735S_WriteChar12Y(const uint8_t* _ch);
extern void ST7735S_WriteChar1216Y(const uint8_t* _ch, uint8_t _R, uint8_t _G, uint8_t _B);

extern void ST7735S_WriteChar1616Y(const uint8_t* _ch);
extern void ST7735S_Printf88(uint8_t _xs, uint8_t _ys, uint8_t *txt, uint8_t _length,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_PrintInt1010(uint8_t xs,uint8_t ys, uint16_t _val,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_Printf1010(uint8_t xs, uint8_t ys, uint8_t *txt,uint8_t _length,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_Printf1216(uint8_t _xs, uint8_t _ys, uint8_t *txt, uint8_t _length,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_PrintChar1010(uint8_t _xs, uint8_t _ys, uint8_t _ch,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_Rectangle(uint8_t _xs, uint8_t _ys, uint8_t _xsize, uint8_t _ysize,uint8_t _R,uint8_t _G, uint8_t _B);
extern void ST7735S_PaintALL(uint8_t R,uint8_t G,uint8_t B);
extern void ST7735S_Demo(void);

#ifdef	__cplusplus
}
#endif

#endif	/* ST7735S_H */


```

```ST7735S.c
#include "ds_ST7735S.h"
#include "PIC32_SPI2.h"
#include "PIC32_Graphics.h"

 const uint8_t  char8Set[38][8] =
{
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//SP88
    {0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x00},//-(0x2D)
    {0x00,0x3e,0x41,0x41,0x41,0x41,0x3e,0x00},//0(0x30)88
    {0x00,0x00,0x00,0x20,0x7f,0x00,0x00,0x00},//1(0x31)88
    {0x00,0x33,0x45,0x49,0x49,0x49,0x31,0x00},//2(0x32)88
    {0x00,0x22,0x41,0x49,0x49,0x49,0x36,0x00},//3(0x33)88
    {0x00,0x0e,0x12,0x22,0x42,0x7f,0x02,0x00},//4(0x34)88
    {0x00,0x79,0x49,0x49,0x49,0x49,0x46,0x00},//5(0x35)88
    {0x00,0x3e,0x49,0x49,0x49,0x49,0x2e,0x00},//6(0x36)88
    {0x00,0x00,0x40,0x41,0x42,0x44,0x78,0x00},//7(0x37)88
    {0x00,0x36,0x49,0x49,0x49,0x49,0x36,0x00},//8(0x38)88
    {0x00,0x32,0x49,0x49,0x49,0x49,0x3e,0x00},//9(0x39)88
    {0x00,0x24,0x4a,0x52,0x52,0x3e,0x02,0x00},//a(0x61)882
    {0x00,0x7c,0x0a,0x12,0x12,0x12,0x0c,0x00},//b(0x62)882
    {0x00,0x1c,0x22,0x22,0x22,0x22,0x14,0x00},//c(0x63)882
    {0x00,0x0c,0x12,0x12,0x12,0x0a,0x7c,0x00},//d(0x64)882
    {0x00,0x3c,0x52,0x52,0x52,0x52,0x24,0x00},//e(0x65)882
    {0x00,0x00,0x10,0x7e,0x90,0x50,0x00,0x00},//f(0x66)882
    {0x00,0x32,0x4a,0x4a,0x4a,0x4a,0x3c,0x00},//g(0x67)882
    {0x00,0xfe,0x10,0x20,0x20,0x20,0x1e,0x00},//h(0x68)882
    {0x00,0x00,0x00,0xbe,0x00,0x00,0x00,0x00},//i(0x69)882
    {0x00,0x0c,0x02,0x02,0x02,0x02,0xbc,0x00},//j(0x6a)882
    {0x00,0x00,0xfe,0x08,0x18,0x24,0x42,0x00},//k(0x6b)882
    {0x00,0x00,0x80,0xfe,0x00,0x00,0x00,0x00},//l(0x6c)882
    {0x00,0x30,0x40,0x7e,0x20,0x7e,0x20,0x7e},//m(0x6d)882
    {0x00,0x7e,0x10,0x20,0x40,0x40,0x3e,0x00},//n(0x6e)882
    {0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00},//o(0x6f)882
    {0x00,0x3e,0x48,0x48,0x48,0x48,0x30,0x00},//p(0x70)882
    {0x00,0x30,0x48,0x48,0x48,0x30,0x7e,0x00},//q(0x71)882
    {0x00,0x7e,0x20,0x40,0x40,0x40,0x30,0x00},//r(0x72)882
    {0x00,0x12,0x2a,0x2a,0x2a,0x2a,0x2c,0x00},//s(0x73)882
    {0x00,0x40,0x40,0xfc,0x42,0x42,0x44,0x00},//t(0x74)882
    {0x00,0x7c,0x02,0x02,0x7c,0x02,0x02,0x00},//u(0x75)882
    {0x00,0x78,0x04,0x02,0x02,0x04,0x78,0x00},//v(0x76)882
    {0x00,0x7c,0x02,0x02,0x7c,0x02,0x02,0x7c},//w(0x77)882
    {0x00,0x42,0x24,0x18,0x18,0x24,0x42,0x00},//x(0x78)882
    {0x00,0x00,0x40,0x20,0x1e,0x20,0x40,0x00},//y(0x79)882
    {0x00,0x42,0x46,0x4a,0x52,0x62,0x42,0x00}//z(0x7a)882
};  

 const uint8_t char10Set[39][20]=
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//SP1010
{0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0f,0x00,0x0f,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//.(0x2e)1010
{0x00,0x00,0xfc,0x00,0xfe,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xfe,0x01,0xfc,0x00},//0(0x30)1010
{0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0xc0,0x01,0xff,0x03,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00},//1(0x31)1010
{0x00,0x00,0xc3,0x00,0xc7,0x01,0x0f,0x03,0x1b,0x03,0x1b,0x03,0x33,0x03,0x63,0x03,0xe3,0x01,0xc3,0x00},//2(0x32)1010
{0x00,0x00,0x86,0x01,0x87,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0xff,0x03,0xfe,0x01,0xcc,0x00},//3(0x33)1010
{0x00,0x00,0x38,0x00,0x7c,0x00,0xcc,0x00,0x8c,0x01,0x0c,0x03,0xff,0x03,0xff,0x03,0x0c,0x00,0x0c,0x00},//4(0x34)1010
{0x00,0x00,0xe6,0x03,0xe7,0x03,0x63,0x03,0x63,0x03,0x63,0x03,0x63,0x03,0x7e,0x03,0x3c,0x03,0x00,0x00},//5(0x35)1010
{0x00,0x00,0xfc,0x00,0xfe,0x01,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x9e,0x01,0x9c,0x00},//6(0x36)1010
{0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x0f,0x03,0x1f,0x03,0x30,0x03,0xe0,0x03,0xc0,0x03,0x80,0x03},//7(0x37)1010
{0x00,0x00,0xce,0x01,0xff,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0xff,0x03,0xce,0x01},//8(0x38)1010
{0x00,0x00,0xc0,0x00,0xe3,0x01,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0xfe,0x01,0xfc,0x00},//9(0x39)1010
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0x01,0xce,0x01,0xce,0x01,0x00,0x00,0x00,0x00,0x00,0x00},//:(0x3A)1010
{0x00,0x00,0xff,0x00,0xff,0x01,0x18,0x03,0x18,0x03,0x18,0x03,0x18,0x03,0x18,0x03,0xff,0x01,0xff,0x00},//A(0x41)1010 14番目
{0x00,0x00,0xfe,0x01,0xff,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0xfe,0x01,0xdc,0x00},//B(0x42)1010
{0x00,0x00,0xfc,0x00,0xfe,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x8e,0x01,0x8c,0x00},//C(0x43)1010
{0x00,0x00,0xfe,0x01,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x87,0x03,0xfe,0x01,0xfc,0x00},//D(0x44)1010
{0x00,0x00,0xfe,0x01,0xff,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03},//E(0x45)1010
{0x00,0x00,0xff,0x01,0xff,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0x03,0x30,0x03},//F(0x46)1010
{0x00,0x00,0xfc,0x00,0xfe,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x33,0x03,0x33,0x03,0xbe,0x01,0x9c,0x00},//G(0x47)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0xff,0x03,0xff,0x03},//H(0x48)1010
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0xff,0x03,0xff,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00},//I(0x49)1010
{0x00,0x00,0x1c,0x00,0x1e,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0xfe,0x03,0xfc,0x03,0x00,0x00,0x00,0x00},//J(0x4A)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x30,0x00,0x78,0x00,0xcc,0x00,0x86,0x01,0x03,0x03,0x03,0x00,0x00,0x00},//K(0x4B)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00},//L(0x4C)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x80,0x01,0xe0,0x00,0x70,0x00,0xe0,0x00,0x80,0x01,0xff,0x03,0xff,0x03},//M(0x4D)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x80,0x01,0xe0,0x00,0x70,0x00,0x18,0x00,0x0e,0x00,0xff,0x03,0xff,0x03},//N(0x4E)1010
{0x00,0x00,0xfc,0x00,0xfe,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xfe,0x01,0xfc,0x00},//O(0x4F)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x18,0x03,0x18,0x03,0x18,0x03,0x18,0x03,0x18,0x03,0xf0,0x01,0xe0,0x00},//P(0x50)1010
{0x00,0x00,0xfc,0x00,0xfe,0x01,0x03,0x03,0x13,0x03,0x1b,0x03,0x0f,0x03,0x86,0x01,0xff,0x00,0x7b,0x00},//Q(0x51)1010
{0x00,0x00,0xff,0x03,0xff,0x03,0x18,0x03,0x18,0x03,0x18,0x03,0x1c,0x03,0x1e,0x03,0xf7,0x01,0xe3,0x00},//R(0x52)1010
{0x00,0x00,0xe6,0x00,0xf7,0x01,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x33,0x03,0x9e,0x01,0x8c,0x00},//S(0x53)1010
{0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0xff,0x03,0xff,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00},//T(0x54)1010
{0x00,0x00,0xfc,0x03,0xfe,0x03,0x07,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x07,0x00,0xfe,0x03,0xfc,0x03},//U(0x55)1010
{0x00,0x00,0xe0,0x03,0xf8,0x03,0x1e,0x00,0x07,0x00,0x03,0x00,0x07,0x00,0x1e,0x00,0xf8,0x03,0xe0,0x03},//V(0x56)1010
{0x00,0x00,0xfc,0x03,0xfe,0x03,0x03,0x00,0x03,0x00,0xfe,0x03,0x03,0x00,0x03,0x00,0xfe,0x03,0xfc,0x03},//W(0x57)1010
{0x00,0x00,0x03,0x03,0x87,0x03,0xce,0x01,0xfc,0x00,0x78,0x00,0xfc,0x00,0xce,0x01,0x87,0x03,0x03,0x03},//X(0x58)1010
{0x00,0x00,0xc0,0x03,0xe0,0x03,0x70,0x00,0x3f,0x00,0x3f,0x00,0x70,0x00,0xe0,0x03,0xc0,0x03,0x00,0x00},//Y(0x59)1010
{0x00,0x00,0x07,0x03,0x4f,0x03,0x7f,0x03,0x3b,0x03,0x33,0x03,0x73,0x03,0xfb,0x03,0xcb,0x03,0x83,0x03},//Z(0x5A)1010


};

 const uint8_t  char1216Set[41][24]=
{
   {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//SP1216
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x1e,0x00,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//。(0x2e)1216
    {0x01,0x00,0x07,0x00,0x0e,0x00,0x18,0x00,0x70,0x00,0xe0,0x00,0x80,0x01,0x00,0x07,0x00,0x0e,0x00,0x38,0x00,0x70,0x00,0xc0},///(0x2F)1612
    {0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0xfc,0x3f,0xf8,0x1f,0x00,0x00},//0(0x30)1612
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x38,0xfe,0x7f,0xfe,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//1(0x31)1612
    {0x00,0x00,0x06,0x1e,0x0e,0x3e,0x1e,0x60,0x3e,0x60,0x76,0x60,0xe6,0x60,0xc6,0x61,0x86,0x63,0x06,0x7f,0x06,0x3e,0x00,0x00},//2(0x32)1612
    {0x00,0x00,0x18,0x18,0x1c,0x38,0x06,0x60,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0xfc,0x3f,0x78,0x1e,0x00,0x00},//3(0x33)1612
    {0x00,0x00,0x78,0x00,0xf8,0x01,0x98,0x03,0x18,0x0f,0x18,0x1c,0x18,0x38,0x18,0x60,0xfe,0x7f,0xfe,0x7f,0x18,0x00,0x00,0x00},//4(0x34)1612
    {0x00,0x00,0x0c,0x7f,0x0e,0x7f,0x06,0x63,0x06,0x63,0x06,0x63,0x06,0x63,0x06,0x63,0x06,0x63,0xfe,0x63,0xfc,0x63,0x00,0x00},//4(0x34)1612
    {0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0xfc,0x70,0x78,0x30,0x00,0x00},//6(0x36)1612
    {0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x7e,0x60,0xfe,0x60,0x80,0x61,0x00,0x63,0x00,0x7e,0x00,0x7c,0x00,0x00},//7(0x37)1612
    {0x00,0x00,0x78,0x1e,0xfc,0x3f,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0xfc,0x3f,0x78,0x1e,0x00,0x00},//8(0x38)1612
    {0x00,0x00,0x00,0x1f,0x86,0x3f,0xc6,0x60,0xc6,0x60,0xc6,0x60,0xc6,0x60,0xc6,0x60,0xc6,0x60,0xfc,0x3f,0xf8,0x1f,0x00,0x00},//9(0x39)1216
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0c,0x78,0x1e,0x78,0x1e,0x30,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},//：(0x3A)1612
    {0x00,0x00,0xfe,0x1f,0xfe,0x3f,0xc0,0x60,0xc0,0x60,0xc0,0x60,0xc0,0x60,0xc0,0x60,0xc0,0x60,0xfe,0x3f,0xfe,0x1f,0x00,0x00},//A(0x41)1612
    {0x00,0x00,0xfc,0x3f,0xfe,0x7f,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0xfc,0x3f,0x78,0x1e,0x00,0x00},//B(0x42)1612
    {0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x3c,0x3c,0x38,0x1c,0x00,0x00},//C(0x43)1612
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x0e,0x70,0x1c,0x38,0xf8,0x1f,0xf0,0x0f,0x00,0x00},//D(0x44)1612
    {0x00,0x00,0xfc,0x3f,0xfe,0x7f,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x00,0x00},//E(0x45)1612
    {0x00,0x00,0xfe,0x3f,0xfe,0x7f,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x00,0x00},//F(0x46)1612
    {0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x06,0x60,0x06,0x60,0x06,0x60,0x86,0x61,0x86,0x61,0x8e,0x61,0xfc,0x39,0xf8,0x19,0x00,0x00},//G(0x47)1612
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xfe,0x7f,0xfe,0x7f,0x00,0x00},//H(0x48)1612
    {0x00,0x00,0x00,0x00,0x06,0x60,0x06,0x60,0x06,0x60,0xfe,0x7f,0xfe,0x7f,0x06,0x60,0x06,0x60,0x06,0x60,0x00,0x00,0x00,0x00},//I(0x49)1612
    {0x00,0x00,0xf8,0x00,0xfc,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xfc,0x7f,0xf8,0x7f,0x00,0x00},//J(0x4A)1612
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x80,0x01,0xc0,0x03,0x60,0x06,0x30,0x0c,0x18,0x18,0x0c,0x30,0x06,0x60,0x02,0x40,0x00,0x00},//K(0x4B)1612
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00},//L(0x4C)
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x00,0x38,0x00,0x1c,0xfe,0x0f,0xfe,0x0f,0x00,0x1c,0x00,0x38,0xfe,0x7f,0xfe,0x7f,0x00,0x00},//M(0x4D)
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x00,0x38,0x00,0x0e,0x80,0x07,0xc0,0x01,0x78,0x00,0x1c,0x00,0xfe,0x7f,0xfe,0x7f,0x00,0x00},//N(0x4E)
    {0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x0e,0x70,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x0e,0x70,0xfc,0x3f,0xf8,0x1f,0x00,0x00},//O(0x4F)
    {0x00,0x00,0xfe,0x3f,0xfe,0x7f,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x00,0x3f,0x00,0x1e,0x00,0x00},//P(0x50)
    {0x00,0x00,0xf0,0x1f,0xf8,0x3f,0x0c,0x60,0x0c,0x60,0x6c,0x60,0x7c,0x60,0x1c,0x60,0x0e,0x60,0xfe,0x3f,0xf6,0x1f,0x06,0x00},//Q(0x51)
    {0x00,0x00,0xfe,0x7f,0xfe,0x7f,0x80,0x61,0xc0,0x61,0xe0,0x61,0xb0,0x61,0x98,0x61,0x8c,0x61,0x06,0x3f,0x02,0x1e,0x00,0x00},//R(0x52)
    {0x00,0x00,0x1c,0x1f,0x9e,0x3f,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0xfc,0x38,0x78,0x18,0x00,0x00},//S(0x53)
    {0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0xfe,0x7f,0xfe,0x7f,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00},//T(0x54)
    {0x00,0x00,0xf8,0x7f,0xfc,0x7f,0x0e,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x0e,0x00,0xfc,0x7f,0xf8,0x7f,0x00,0x00},//U(0x55)
    {0x00,0x00,0xe0,0x7f,0xf0,0x7f,0x38,0x00,0x1c,0x00,0x0e,0x00,0x0e,0x00,0x1c,0x00,0x38,0x00,0xf0,0x7f,0xe0,0x7f,0x00,0x00},//V(0x56)
    {0x00,0x00,0x00,0x7f,0xfc,0x7f,0xfe,0x00,0x0c,0x00,0xf8,0x7f,0xf8,0x7f,0x0c,0x00,0xfe,0x00,0xfc,0x7f,0x00,0x7f,0x00,0x00},//W(0x57)
    {0x02,0x40,0x06,0x60,0x0c,0x30,0x38,0x1c,0x70,0x0e,0xc0,0x03,0xc0,0x03,0x70,0x0e,0x18,0x1c,0x0c,0x30,0x06,0x60,0x02,0x40},//X(0x57)
    {0x00,0x40,0x00,0x60,0x00,0x30,0x00,0x1c,0x00,0x0e,0xfe,0x07,0xfe,0x07,0x00,0x0e,0x00,0x1c,0x00,0x30,0x00,0x60,0x00,0x40},//Y(0x58)
    {0x00,0x00,0x0e,0x60,0x1e,0x60,0x36,0x64,0x66,0x66,0xc6,0x63,0xc6,0x63,0xc6,0x66,0x66,0x6c,0x26,0x78,0x06,0x70,0x00,0x00},//Z(0x59)
    {0x01,0x00,0x07,0x00,0x0e,0x00,0x18,0x00,0x70,0x00,0xe0,0x00,0x80,0x01,0x00,0x07,0x00,0x0e,0x00,0x38,0x00,0x70,0x00,0xc0}///(0x2F)

 };

 const uint8_t  char1616Set[6][32]=
{
    {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},//SP
    {0x00,0x00,0xfe,0x7f,0x00,0x49,0x00,0x49,0x00,0x49,0x52,0x49,0x7e,0x7f,0x50,0x00,0x50,0x00,0x7e,0x7f,0x50,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0xfe,0x7f,0x00,0x00},//開
    {0x00,0x00,0x02,0x08,0xe4,0x3f,0x18,0x08,0x18,0x08,0xe4,0x3f,0x02,0x08,0x00,0x00,0x7e,0x03,0x42,0x0d,0x42,0x31,0x42,0x01,0x42,0x05,0x42,0x03,0x7e,0x01,0x80,0x00},//始
    {0x00,0x00,0xf8,0x1f,0xfc,0x3f,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x1c,0x3c,0x18,0x1c,0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x48,0x00,0x30,0x00,0x00},//摂氏
    {0x00,0x00,0x00,0x00,0x06,0x0c,0x0c,0x1e,0x18,0x33,0x30,0x33,0x60,0x1e,0xc0,0x0c,0x80,0x01,0x18,0x03,0x3c,0x06,0x66,0x0c,0x66,0x18,0x3c,0x30,0x18,0x60,0x00,0x00},//％
    {0x00,0x00,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xfe,0x7f,0xfc,0x3f,0xf8,0x1f,0xf0,0x0f,0xe0,0x07,0xc0,0x03,0x80,0x01,0x00,0x00}//矢印右
};

volatile _ST7735 ST7735;
volatile uint8_t *psv_pt;

void ST7735S_Init(void)
{
    uint8_t x,y;
    uint16_t i,j;
   

    ST7735S_Write(ST7735_CM,0x01);
    __delay_ms(120);
    ST7735S_Write(ST7735_CM,0x11);
     __delay_ms(120);
    ST7735S_Write(ST7735_CM,0x28);
    
    ST7735S_Write(ST7735_CM,0x36);
    ST7735S_Write(ST7735_DT,0x60);//Camera QQVGA
    //ST7735S_Write(ST7735_DT,0b00001000);//BGR order
    ST7735S_Write(ST7735_CM,0x3a);
    ST7735S_Write(ST7735_DT,0x05);//16bits/Pixel(RGB565)
    //ST7735S_Write(ST7735_DT,0x06);//18bits/Pixel(RGB666)
    //ST7735S_Write(ST7735_DT,0x03);//Format RGB444
    
    ST7735S_Write(ST7735_CM,0x20);//Display Inversion OFF
    ST7735S_Write(ST7735_CM,0x38);//Idle mode off
    ST7735S_Write(ST7735_CM,0x26);//
    ST7735S_Write(ST7735_DT,0x08);
    //ST7735S_Write(ST7735_DT,0x04);
    //ST7735S_Write(ST7735_DT,0x02);
    
    ST7735S_Write(ST7735_CM,0x13);
    ST7735S_Write(ST7735_CM,0x29);
    
    //コラムアドレスセット X=10
    ST7735S_Write(ST7735_CM,0x2a);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x9F);//127
    //Row Address Set Y=10
    ST7735S_Write(ST7735_CM,0x2b);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x7F);//159
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0=1;
    SPI2_Start();
    for(i=0; i<20480;i++)
    {
        /*SPI2_Write(backColor_R);
        SPI2_Write(backColor_G);
        SPI2_Write(backColor_B);*/
        SPI2_Write(0xFF);
        SPI2_Write(0xFF);
        SPI2_Write(0xFF);
    }
    SPI2_Stop();
    
    ST7735S_Write(ST7735_CM,0x3a);
    ST7735S_Write(ST7735_DT,0x55);//16bits/Pixel(RGB565)
    
    //ST7735S_Demo();
    
}

//_CD Command 0  Data:1
//_data byte data
void ST7735S_Write(uint8_t _CD, uint8_t _data)
{
    ST7735_A0=_CD;
    SPI2_Start();
    SPI2_Write(_data);
    SPI2_Stop();
}

//_xs 0
//_xe 0
//_ys 0
//_ys 127
void ST7735S_AddSet(uint8_t _xs,uint8_t _xe, uint8_t _ys,uint8_t _ye)
{
     //コラムアドレスセット
    ST7735S_Write(ST7735_CM,0x2a);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,_ys);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,_ye);//127
    //Row Address Set
    ST7735S_Write(ST7735_CM,0x2b);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,_xs);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,_xe);//159
}

void ST7735S_WriteChar8X(const uint8_t* _ch)
{
    uint8_t i,j,ch,buf;
    uint8_t* psv_pt;
    psv_pt=(uint8_t*)_ch;
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();
    
    for(i=0; i<8; i++)
    {
        ch=*(psv_pt++);
        j=0x01;
        do
        {
            buf=ch&j;
            if(buf!=0x00)
            {
                SPI2_Write(0xFC);
                SPI2_Write(0xFC);
                SPI2_Write(0x00);
            }
            else{
                SPI2_Write(0x00);
                SPI2_Write(0x00);
                SPI2_Write(0x00);
            }
            j<<=1;
        }while(j!=0x00);
    }
    SPI2_Stop();    
}    

void ST7735S_WriteChar8Y(const uint8_t* _ch,uint8_t _R,uint8_t _G, uint8_t _B)
{
    uint8_t x,y,ch,buf;
    uint8_t* psv_pt;
    psv_pt=(uint8_t*)_ch;
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();
    
    for(x=0; x<8; x++)
    {
        ch=*(psv_pt++);
        y=0x01;
        do
        {
            buf=ch&y;
            if(buf!=0x00)
            {
                SPI2_Write(_R);
                SPI2_Write(_G);
                SPI2_Write(_B);
            }
            else{
                SPI2_Write(backColor_R);
                SPI2_Write(backColor_G);
                SPI2_Write(backColor_B);
            }
            y<<=1;
        }while(y!=0x00);
    }
    SPI2_Stop();    
}    

void ST7735S_WriteChar10Y(const uint8_t* _ch, uint8_t _R, uint8_t _G, uint8_t _B)
{
    uint8_t x,y,bitmask,buf;
    uint8_t ch[2];
    uint8_t* psv_pt;
    psv_pt=(uint8_t*)_ch;
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();

    for(x=0; x<10; x++)
    {
        for(y=0; y<2; y++)
        {
            ch[0]=*(psv_pt++);
            bitmask=0x01;
            do
            {
                buf=ch[0]&bitmask;
                if(buf!=0x00)
                {
                    SPI2_Write(_R);
                    SPI2_Write(_G);
                    SPI2_Write(_B);
                }
                else{
                    SPI2_Write(backColor_R);
                    SPI2_Write(backColor_G);
                    SPI2_Write(backColor_B);
                }
                bitmask<<=1;
                if(y==1 && bitmask==0x04)
                    bitmask=0x00;
            }while(bitmask!=0x00);
        }
    }
    SPI2_Stop();    
}    

void ST7735S_WriteChar12Y(const uint8_t* _ch)
{
    uint8_t x,y,bitmask,buf;
    uint8_t ch[2];
    uint8_t* psv_pt;
    psv_pt=(uint8_t*)_ch;
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();

    for(x=0; x<12; x++)
    {
        for(y=0; y<2; y++)
        {
            ch[0]=*(psv_pt++);
            bitmask=0x01;
            do
            {
                buf=ch[0]&bitmask;
                if(buf!=0x00)
                {
                    SPI2_Write(char12Y_R);
                    SPI2_Write(char12Y_G);
                    SPI2_Write(char12Y_B);
                }
                else{
                    SPI2_Write(backColor_R);
                    SPI2_Write(backColor_G);
                    SPI2_Write(backColor_B);
                }
                bitmask<<=1;
                if(y==1 && bitmask==0x10)
                    bitmask=0x00;
            }while(bitmask!=0x00);
        }
    }
    SPI2_Stop();    
}    

void ST7735S_WriteChar1216Y(const uint8_t* _ch, uint8_t _R, uint8_t _G, uint8_t _B)
{
    uint8_t x,y,bitmask,buf;
    uint8_t ch[2];
    uint8_t* psv_pt;
    psv_pt=(uint8_t*)_ch;
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();
    
    for(x=0; x<12; x++)
    {
        for(y=0; y<2; y++)
        {
            ch[0]=*(psv_pt++);
            bitmask=0x01;
            do
            {
                buf=ch[0]&bitmask;
                if(buf!=0x00)
                {
                    SPI2_Write(_R);
                    SPI2_Write(_G);
                    SPI2_Write(_B);
                }
                else{
                    SPI2_Write(backColor_R);
                    SPI2_Write(backColor_G);
                    SPI2_Write(backColor_B);
                }
                bitmask<<=1;
            }while(bitmask!=0x00);
        }
    }
    SPI2_Stop();    
} 

void ST7735S_WriteChar1616Y(const uint8_t* _ch)
{
    uint8_t x,y,bitmask,buf;
    uint8_t ch[2];
    uint8_t* psv_pt;
    psv_pt=(uint8_t*)_ch;
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();
    
    for(x=0; x<16; x++)
    {
        for(y=0; y<2; y++)
        {
            ch[0]=*(psv_pt++);
            bitmask=0x01;
            do
            {
                buf=ch[0]&bitmask;
                if(buf!=0x00)
                {
                    SPI2_Write(char16Y_R);
                    SPI2_Write(char16Y_G);
                    SPI2_Write(char16Y_B);
                }
                else{
                    SPI2_Write(backColor_R);
                    SPI2_Write(backColor_G);
                    SPI2_Write(backColor_B);
                }
                bitmask<<=1;
            }while(bitmask!=0x00);
        }
    }
    SPI2_Stop();    
}   

/*---------------------------------------------------**/
void ST7735S_Printf88(uint8_t _xs, uint8_t _ys, uint8_t *txt, uint8_t _length,uint8_t _R,uint8_t _G, uint8_t _B)
{
    unsigned int i;
    unsigned int buf[5];
    uint8_t num;
   
    //アルファベット
    for(i=0; i<_length; i++)
    {
        ST7735S_AddSet(_xs,_xs+7,_ys,_ys+7);
        //num=*txt-char88Offset;
        if(*txt==0x20)num=0;
        if(*txt==0x2D)num=1;
        if(0x30<=*txt && *txt<=0x39)
        {
            num=*txt-0x30+char88OffsetNumber;
        }
        if(0x61<=*txt && *txt<=0x7A)
        {
            num=*txt-char88Offset+char88OffsetNumber+9;
        }
        ST7735S_WriteChar8Y(char8Set[num],_R,_G,_B);
        txt++;
        _xs+=7;
    }
}

void ST7735S_PrintInt1010(uint8_t xs, uint8_t ys, uint16_t _val,uint8_t _R,uint8_t _G, uint8_t _B)
{
    unsigned int i;
    unsigned int buf[5];
    
    if(_val>=0xFFFF) return;
    
    buf[0]=_val/10000;
    buf[1]=(_val%10000)/1000;
    buf[2]=(_val%1000)/100;
    buf[3]=(_val%100)/10;
    buf[4]=_val%10;
    
    //アルファベット
    for(i=0; i<=4; i++)
    {
        ST7735S_AddSet(xs,xs+9,ys,ys+9);
        ST7735S_WriteChar10Y(char10Set[buf[i]+2],_R,_G,_B);
        xs+=10;
    }
}

void ST7735S_Printf1010(uint8_t _xs, uint8_t _ys, uint8_t *txt, uint8_t _length,uint8_t _R,uint8_t _G, uint8_t _B)
{
    unsigned int i;
    //unsigned int buf[5];
    uint8_t num;
   
    for(i=0; i<_length; i++)
    {
        ST7735S_AddSet(_xs,_xs+9,_ys,_ys+9);
        
        if(*txt==0x20)num=0;
        if(*txt==0x2E)num=1;
        if(0x30<=*txt && *txt<=0x3A)
        {
            num=*txt-0x30+char1010OffsetNumber;
        }
        if(0x41<=*txt && *txt<=0x5A)
        {
            num=*txt-char1010OffsetAZ;
        }
        if(*txt==0x20)num=0;
        if(*txt==0x2E)num=1;
        ST7735S_WriteChar10Y(char10Set[num],_R,_G,_B);
        txt++;
        _xs+=10;
    }
}

void ST7735S_Printf1216(uint8_t _xs, uint8_t _ys, uint8_t *txt, uint8_t _length,uint8_t _R,uint8_t _G, uint8_t _B)
{
    unsigned int i;
    //unsigned int buf[5];
    uint8_t num;
   
    for(i=0; i<_length; i++)
    {
        ST7735S_AddSet(_xs,_xs+11,_ys,_ys+15);
        
        if(*txt==0x20)num=0;
        if(*txt==0x2E)num=1;
        if(0x30<=*txt && *txt<=0x3A)
        {
            num=*txt-0x30+char1216OffsetNumber;
        }
        if(0x41<=*txt && *txt<=0x5A)
        {
            num=*txt-char1216OffsetAZ;
        }
        if(*txt==0x20)num=0;
        if(*txt==0x2E)num=1;
        ST7735S_WriteChar1216Y(char1216Set[num],_R,_G,_B);
        txt++;
        _xs+=11;
    }
}
void ST7735S_PrintChar1010(uint8_t _xs, uint8_t _ys, uint8_t _ch,uint8_t _R,uint8_t _G, uint8_t _B)
{
    uint8_t num;
    
    if(_ch==0x20)num=0;
    if(_ch==0x2E)num=1;
    if(0x30<=_ch && _ch<=0x3A)
    {
        num=_ch-0x30+char1010OffsetNumber;
    }
    if(0x41<=_ch && _ch<=0x5A)
    {
        num=_ch-char1010OffsetAZ;
    }
    ST7735S_AddSet(_xs,_xs+9,_ys,_ys+9);
    ST7735S_WriteChar10Y(char10Set[num],_R,_G,_B);
}

/*------------------------------------------------------*/



void ST7735S_Rectangle(uint8_t _xs, uint8_t _ys, uint8_t _xsize, uint8_t _ysize,uint8_t _R,uint8_t _G, uint8_t _B)
{
    uint8_t x,y;
    
    ST7735S_AddSet(_xs,_xs+_xsize,_ys,_ys+_ysize);
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0= ST7735_DT;
    SPI2_Start();
    for(x=0; x<=_xsize; x++)
    {
        for(y=0; y<=_ysize; y++)
        {
            SPI2_Write(_R);
            SPI2_Write(_G);
            SPI2_Write(_B);
        }
    }
    SPI2_Stop();    
}


void ST7735S_PaintALL(uint8_t _R,uint8_t _G,uint8_t _B)
{
    unsigned int i;
    //コラムアドレスセット X=10
    ST7735S_Write(ST7735_CM,0x2a);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x7F);//127
    //Row Address Set Y=10
    ST7735S_Write(ST7735_CM,0x2b);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x00);
    ST7735S_Write(ST7735_DT,0x9F);//159
    
    ST7735S_Write(ST7735_CM,0x2c);
    ST7735_A0=1;
    SPI2_Start();
    for(i=0; i<20480;i++)
    {
        SPI2_Write(_R);
        SPI2_Write(_G);
        SPI2_Write(_B);
    }
    SPI2_Stop();
}

void ST7735S_Demo(void)
{
    int x,y,i,j;
    #define testST7735S 
    #ifdef testST7735S 
   //長方形
  /*  for(i=0; i<=3; i++)
    {
        ST7735S_Rectangle(0,(uint8_t)10*i,10,10,0x30,0x00,0xF0);
    }*/
    
    //数字1010
    x=0; y=0;
    //for(i=0; i<13; i++)
    for(i=0; i<13; i++)
    {
        ST7735S_AddSet(x,x+9,y,y+9);
        ST7735S_WriteChar10Y(char10Set[i],0x30,0x40,0x40);
        x+=10;
    }
    __delay_ms(100);
    //アルファベット1010
    x=0; y=20; j=0;
    for(i=13; i<13+26; i++)
    {
        ST7735S_AddSet(x,x+9,y,y+9);
        ST7735S_WriteChar10Y(char10Set[i],0x30,0x00,0xF0);
        x+=10;
        j++;
        if(j%15==0)
        {
            y+=12;
            x=0;
        }
    }
     __delay_ms(100);
    //数字88
    x=0; y=45; j=0;
    for(i=0; i<12; i++)
    {
        ST7735S_AddSet(x,x+7,y,y+7);
        ST7735S_WriteChar8Y(char8Set[i],0x10,0x30,0x70);
        x+=8;
        j++;
        if(j%15==0)
        {
            y+=10;
            x=0;
        }
    }
     __delay_ms(100);
     //アルファベット88
    x=0; y=55; j=0;
    for(i=12; i<12+26; i++)
    {
        ST7735S_AddSet(x,x+7,y,y+7);
        ST7735S_WriteChar8Y(char8Set[i],0x10,0x40,0xA0);
        x+=8;
        j++;
        if(j%20==0)
        {
            y+=10;
            x=0;
        }
    }
     __delay_ms(100);
    //数字1216
    x=0; y=75; j=0;
    for(i=0; i<13; i++)
    {
        ST7735S_AddSet(x,x+11,y,y+15);
        ST7735S_WriteChar1216Y(char1216Set[i],0x10,0x30,0xF0);
        x+=12;
    }
     __delay_ms(100);
    //アルファベット1216
    x=0; y=93; j=0;
    for(i=14; i<14+26; i++)
    {
        ST7735S_AddSet(x,x+11,y,y+15);
        ST7735S_WriteChar1216Y(char1216Set[i],0xF0,0x70,0x00);
        x+=12;
         j++;
        if(j%13==0)
        {
            y+=17;
            x=0;
        }
    }
     __delay_ms(100);
    
#endif
}


```

```OV7670Camera.h
/* 
 * File:   OV7670Camera.h
 * Author: h
 *
 * Created on 2022/01/05, 5:22
 */

#ifndef OV7670CAMERA_H
#define	OV7670CAMERA_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
#include <stdbool.h>
#include <stdio.h>
    
//カメラ割込み３線対応変数-----------------------
typedef struct{
    uint8_t Hcolor[10];//160*120*2未使用。(未使用：sprite1を使用。)
    uint16_t HpixCounter;//水平方向ピクセルカウンタ
    uint16_t LineCounter;//垂直方向行番号カウンタ
    uint16_t portBval;//カメラパラレル８ビット受信変数：未使用(DMA使用のため)
    bool fg_TFT_Send;//行データ受信完了フラグ：未使用(DMA使用のため)
}_OV7670;
extern volatile _OV7670 OV7670;

extern void OV7670_Init(void);

#ifdef	__cplusplus
}
#endif

#endif	/* OV7670CAMERA_H */


```
```OV7670Camera.c
#include "OV7670Camera.h"

volatile _OV7670 OV7670;

//OV7670 データ受信用変数初期化関数。
void OV7670_Init(void)
{
    OV7670.HpixCounter=0;//ピクセルカウンタ
    OV7670.LineCounter=0;//行カウンタ
    OV7670.fg_TFT_Send=false;//行データ受信フラグ：未使用
    TRISE=0x000000FF;//カメラ８ビットパラレルデータ入力ポート
}
```
```OV7670_Code.h
#include <xc.h>
    
#define OV7670deviceAdd 0x42
#define initRegNumber 166



//今回は使用せず。
struct regval_list{
  uint8_t reg_num;
  uint16_t value;
};


extern  const uint8_t OV7670Reg[166][2];   


extern void OV7670_RegInit( const uint8_t pt[][2]);
extern void camInit(void);
extern void cammode_select(void);
extern void setColor( const uint8_t pt[][2]);
extern void setRes( const uint8_t pt[][2]);
extern void stopAEC(void);
```
```OV7670_Code.c
#include "PIC32_I2C2SCCB.h"
#include "OV7670_arCode.h"
#include "peripheral.h"


//OV７６７０レジスタ初期化値
const uint8_t OV7670Reg[166][2]=
  {
    {0x3a,0x05},
    {0x12,0},
#define QQVGA2
#ifdef QQVGA1
    {0x17, 0x16},//HSTART	
    {0x18, 0x04},//HSTOP
	{0x32, 0xA4},//HREF	
    
    {0x19, 0x02},//VSTART       	
    {0x1a, 0x7a}, //VSTOP	
    {0x03, 0x0a},  //VREF
	      
#endif
    
#ifdef QQVGA2
    {0x17, 0x16},//HSTART	
    {0x18, 0x04},//HSTOP
	{0x32, 0x80},//HREF	
    
    {0x19, 0x02},//VSTART       	
    {0x1a, 0x7a}, //VSTOP	
    {0x03, 0x0a},  //VREF
	      
#endif
	/* Gamma curve values */
#define GammaCurve4
#ifdef GammaCurve1
	{0x7a, 0x20},		{0x7b, 0x10},
	{0x7c, 0x1e},		{0x7d, 0x35},
	{0x7e, 0x5a},		{0x7f, 0x69},
	{0x80, 0x76},		{0x81, 0x80},
	{0x82, 0x88},		{0x83, 0x8f},
	{0x84, 0x96},		{0x85, 0xa3},
	{0x86, 0xaf},		{0x87, 0xc4},
	{0x88, 0xd7},		{0x89, 0xe8},
#endif
#ifdef GammaCurve2
    {0x7a, 0x40},		{0x7b, 0x04},
	{0x7c, 0x08},		{0x7d, 0x10},
	{0x7e, 0x20},		{0x7f, 0x28},
	{0x80, 0x30},		{0x81, 0x38},
	{0x82, 0x40},		{0x83, 0x48},
	{0x84, 0x50},		{0x85, 0x60},
	{0x86, 0x70},		{0x87, 0x90},
	{0x88, 0xB0},		{0x89, 0xD0},
#endif
        //0.8
#ifdef GammaCurve3
    {0x7a, 0x4D},		{0x7b, 0x01},
	{0x7c, 0x03},		{0x7d, 0x08},
	{0x7e, 0x13},		{0x7f, 0x19},
	{0x80, 0x1F},		{0x81, 0x26},
	{0x82, 0x2D},		{0x83, 0x34},
	{0x84, 0x3b},		{0x85, 0x4b},
	{0x86, 0x5b},		{0x87, 0x7c},
	{0x88, 0xA0},		{0x89, 0xC5},
#endif
        //0.5
#ifdef GammaCurve4
    {0x7a, 0x73},		{0x7b, 0x00},
	{0x7c, 0x00},		{0x7d, 0x01},
	{0x7e, 0x04},		{0x7f, 0x06},
	{0x80, 0x09},		{0x81, 0x0C},
	{0x82, 0x10},		{0x83, 0x14},
	{0x84, 0x19},		{0x85, 0x24},
	{0x86, 0x31},		{0x87, 0x51},
	{0x88, 0x79},		{0x89, 0xA9},
#endif
        //1.5
#ifdef GammaCurve5
    {0x7a, 0x22},		{0x7b, 0x1F},
	{0x7c, 0x2D},		{0x7d, 0x3F},
	{0x7e, 0x5A},		{0x7f, 0x64},
	{0x80, 0x6E},		{0x81, 0x77},
	{0x82, 0x7F},		{0x83, 0x87},
	{0x84, 0x8E},		{0x85, 0x9C},
	{0x86, 0xA8},		{0x87, 0xBF},
	{0x88, 0xD3},		{0x89, 0xE6},
#endif
	
    {0x13,0x80|0x40},//COM8	
    {0x00,0},//GAIN
    {0x10,0},
    {0x0d,0x40},//COM4
	{0x14,0x18},//COM9
    {0xa5,0x05},//BD50MAX
    {0xab,0x07},
    {0x24,0x95},//AEW
    {0x25,0x33},//AEB
    {0x26,0xe3},
    {0x9f,0x78},//AEC,AGC
    {0xa0,0x68},
    {0xa1, 0x03},
    {0xa6,0xd8},
    {0xa7,0xd8},
    {0xa8,0xf0},
    {0xa9,0x90},
    {0xaa,0x94},
    {0x13,0x80|0x40|0x04|0x01},
	{0x30,0},
    {0x31,0},
    {0x0e,0x61},    
    {0x0f,0x4b},
	{0x16, 0x02},		
    {0x1e,0x07},
	{0x21, 0x02},		
    {0x22, 0x91},
	{0x29, 0x07},		
    {0x33, 0x0b},
	{0x35, 0x0b},		
    {0x37, 0x1d},
	{0x38, 0x71},		
    {0x39, 0x2a},
    {0x3c,0x78},
    {0x4d, 0x40},
	{0x4e, 0x20},		
    {0x69,0},
	{0x74,0x10},
	{0x8d, 0x4f},		
    {0x8e, 0},
	{0x8f, 0},		
    {0x90, 0},
	{0x91, 0},		
    {0x96, 0},
	{0x9a, 0},		
    {0xb0, 0x84},
	{0xb1, 0x00},		
    {0xb2, 0x0e},
	{0xb3, 0x82},		
    {0xb8, 0x0a},
	{0x59, 0x88},		{0x5a, 0x88},
	{0x5b, 0x44},		{0x5c, 0x67},
	{0x5d, 0x49},		{0x5e, 0x0e},
	{0x6c, 0x0a},		{0x6d, 0x55},
	{0x6e, 0x11},		{0x6f, 0x9e}, 
	{0x4f, 0x99},		{0x50, 0x99},
	{0x51, 0},          {0x52, 0x28},
	{0x53, 0x71},		{0x54, 0x99},
	{0x58, 0x9E},
    {0x41,0x08},
    {0x3f,0},
	{0x75, 0x05},
    {0x76,0xe1},
	{0x4c, 0},		
    {0x77, 0x01},
    {0x3d,0x48},
	{0x4b, 0x09},
	{0xc9, 0x60},		
	{0x56, 0x40},
	{0x34, 0x11},		
    {0x3b,0x02|0x10},
	{0xa4, 0x82},		
    {0x55, 0x18},
    {0x56, 0x50},
    {0x6F,0x9F},   
	{0xff, 0xff}	/* END MARKER */
};



//OV7670初期値設定関数
void OV7670_RegInit(const uint8_t pt[][2])
{
    uint8_t ret;
    uint16_t i;
    
    i=0;
    do
    {
        ret=I2C2_b2Write(OV7670deviceAdd,pt[i][0],pt[i][1],true);
        if(ret!=true)
        {
            printf("error[%x]\r",i);
        }
        i++;
    }while(pt[i][0]!=0xFF);
}
//カメラ初期化関数
void camInit(void){
  I2C2_b2Write(OV7670deviceAdd,0x12, 0x80,true); //レジスタリセット
  __delay_ms(100);
  __delay_ms(100);
  __delay_ms(100);
  OV7670_RegInit(OV7670Reg);
  //以下２行はなくてもいいかも。
  I2C2_b2Write(OV7670deviceAdd,0x15,0x20,true);//PCLK does not toggle on HBLANK.
  I2C2_b2Write(OV7670deviceAdd,0x13, 0xEf,true); // Set ACE
}
//カメラ画面サイズ、カラー設定、クロック設定
void cammode_select(void)
{
    uint8_t clkspm,clkspc,com7s;
    
    // QQVGA
    com7s = 0x00;
    //カラーバーの出力RGB444 "RGBx"の順番　カメラﾓｰﾄﾞの出力"BGRx"
    //混乱します。RGB565の使用をおすすめします。
//#define testpatternColorBar      
#ifdef testpatternColorBar
    I2C2_b2Write(OV7670deviceAdd,0x70, 0x3a,true);       
    I2C2_b2Write(OV7670deviceAdd,0x71, 0xB5,true); 
#else
    I2C2_b2Write(OV7670deviceAdd,0x70, 0x3a,true); 
    I2C2_b2Write(OV7670deviceAdd,0x71, 0x35,true); 
#endif
    I2C2_b2Write(OV7670deviceAdd,0x72, 0x22,true);
    I2C2_b2Write(OV7670deviceAdd,0x73, 0xf2,true); 
    I2C2_b2Write(OV7670deviceAdd,0x0c, 0x04,true);
    I2C2_b2Write(OV7670deviceAdd,0x3e, 0x1a,true);
    I2C2_b2Write(OV7670deviceAdd,0xa2, 0x02,true);
     
    //カラー設定 RGB565をお勧めします。  
    //COM7(0x12)　：画面フォーマット指定 QQVGA
    //　　　　　　 ：RGBフォーマット指定 RGB使用
    com7s = 4; // RGB565
    I2C2_b2Write(OV7670deviceAdd,0x40, 0xD0,true); //RGB565
    //0x11CLKRCレジスタでクロックを分周して速度を変更します。
    //I2C2_b2Write(OV7670deviceAdd,0x6B, 0x4a,true); // PLL　4times
    I2C2_b2Write(OV7670deviceAdd,0x6B, 0x0a,true); // PLL　1times
    //I2C2_b2Write(OV7670deviceAdd,0x11, 0x81,true); // ON ReferenceCLK enabled.
    I2C2_b2Write(OV7670deviceAdd,0x11, 0x82,true); // セラロック＋74HC04クロック:Speed20Mhz/6=3.3Mhz
    
#ifdef testpatternColorBar     
    com7s+=2;//color bar
    #endif
    I2C2_b2Write(OV7670deviceAdd,0x12 , com7s,true); 
    //レンズ位置 調節すると写る場合があるかも、今回は使用せず。

    I2C2_b2Write(OV7670deviceAdd,0x62 , 0x00,true); //x
    I2C2_b2Write(OV7670deviceAdd,0x63 , 0x00,true); //y

    //上下さかさまVFlipMirror
    I2C2_b2Write(OV7670deviceAdd,0x1E , 0x30,true); 

     //I2C2_b2Write(OV7670deviceAdd,0x41 , 0x38,true);
     //
     I2C2_b2Write(OV7670deviceAdd,0x41 , 0x38,true); 
      //sharpness
     I2C2_b2Write(OV7670deviceAdd,0x3F, 0x03,true);
    //AWB R,B
     I2C2_b2Write(OV7670deviceAdd,0x64 , 0x01,true); 
     I2C2_b2Write(OV7670deviceAdd,0x46 , 0x01,true); 
     //black level Control
     I2C2_b2Write(OV7670deviceAdd,0xB1 , 0x04,true); 
     //ADC Control
     //I2C2_b2Write(OV7670deviceAdd,0x20 , 0x0F,true); //×0.66倍
     I2C2_b2Write(OV7670deviceAdd,0x20 , 0x04,true); //×1倍
     //Contrast Center automatically
     I2C2_b2Write(OV7670deviceAdd,0x58 , 0x1E,true); 
}
//カラー初期化関数
void setColor( const uint8_t pt[][2])
{
    OV7670_RegInit(pt);
}
//画面初期化設定
void setRes( const uint8_t pt[][2])
{
    I2C2_b2Write(OV7670deviceAdd,0x0c, 0x04,true); // REG_COM3 enable scaling
    OV7670_RegInit(pt);
}
//AEC自動輝度調整を停止関数
void stopAEC(void)
{
    //AEC停止
    I2C2_b2Write(OV7670deviceAdd,0x13,0xC0,true);//AE停止
    I2C2_b2Write(OV7670deviceAdd,0x10,0x64,true);//AECH
}
```