(SSD1306)高速にグラフを表示させる(No_VRAM)(UNO)




x 過去ログをみよ

目的
グラフ表示

メインの処理

```c++

//↓開始　グラフのメイン処理 x=0...127 , y=0...64 
if (y == y_[x]) {
   Dot(x, y, 1); //白のドットを打つ
} else {
   Dot(x, y, 0); //黒のドットを打つ
}//end if
//↑終了

```


結果

![o_coq340.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/64620be5-01a1-4524-8543-786531be6769.jpeg)


プログラム



```c++



//秋月のOLEDとアイテンドウのOLEDのアドレスは3C
//SSD1306_no_vram_graph1_UNO_1

//インクルド
#include <Arduino.h>
#include <Wire.h>


//定義(SSD1306)
#define MAX_PAGE                   (7)
#define MAX_COL                    (127)

#define COMMAND_MODE               0x80 // continuation bit is set!
#define DATA_MODE                  0x40

#define SET_COLUMN_ADDRESS         0x21 // takes two bytes, start address and end address of display data RAM
#define SET_PAGE_ADDRESS           0x22 // takes two bytes, start address and end address of display data RAM

#define SET_MEMORY_ADDRESSING_MODE 0x20 // takes one byte as given above
#define HORIZONTAL_ADDRESSING_MODE 0x00

#define SET_SEGMENT_REMAP_0        0xA0 // column address 0 is mapped to SEG0 (Reset)
#define SET_SEGMENT_REMAP_127      0xA1 // column address 127 is mapped to SEG0

#define SET_COMMON_REMAP_0         0xC0 // row address  0 is mapped to COM0 (Reset)
#define SET_COMMON_REMAP_63        0xC8 // row address 63 is mapped to COM0


//I2Cに配列を転送する
void write_s(uint8_t *str1, uint8_t len1) {

  Wire.beginTransmission(  0x3c  );

  for (int ii = 0; ii < len1; ii++) {

    //一文字出力
    Wire.write(*str1 ++);

  }//for

  Wire.endTransmission();

}//write_s


//セットページアドレス
void setPageAddress(uint8_t start, uint8_t end)
{
  uint8_t databytes[6] = {COMMAND_MODE, SET_PAGE_ADDRESS, COMMAND_MODE, start, COMMAND_MODE, end};
  write_s(databytes, 6);
}//setPageAddress


//セットカラムアクセス
void setColumnAddress(uint8_t start, uint8_t end)
{
  uint8_t databytes[6] = {COMMAND_MODE, SET_COLUMN_ADDRESS, COMMAND_MODE, start, COMMAND_MODE, end};
  write_s(databytes, 6);
}//setColumnAddress


//セットメモリーアドレシングモード
void setMemoryAddressingMode()
{
  uint8_t databytes[4] = {COMMAND_MODE, SET_MEMORY_ADDRESSING_MODE, COMMAND_MODE, HORIZONTAL_ADDRESSING_MODE};
  write_s(databytes, 4);
}//setMemoryAddressingMode


//セットディスプレー Flip
void setDisplayFlip(int left, int down)
{
  if ( left == 0) {
    // column address   0 is mapped to SEG0 (Reset)
    //_sendCommand(SET_SEGMENT_REMAP_0);
    uint8_t databytes[2] = {COMMAND_MODE, SET_SEGMENT_REMAP_0};
    write_s(databytes, 2);
  } else {
    // column address 127 is mapped to SEG0
    //_sendCommand(SET_SEGMENT_REMAP_127);
    uint8_t databytes[2] = {COMMAND_MODE, SET_SEGMENT_REMAP_127};
    write_s(databytes, 2);
  }//end if

  if ( down == 0) {
    // Reset mode
    //_sendCommand(SET_COMMON_REMAP_0);
    uint8_t databytes[2] = {COMMAND_MODE, SET_COMMON_REMAP_0};
    write_s(databytes, 2);
  } else {
    // Flip Up/Down (Need to rewrite display before H effect shows)
    //_sendCommand(SET_COMMON_REMAP_63);
    uint8_t databytes[2] = {COMMAND_MODE, SET_COMMON_REMAP_63};
    write_s(databytes, 2);
  }//end if
}//setDisplayFlip


//8バイト分まとめて出力
void put8byte(uint8_t qq) {

  //データの配列の定義
  static uint8_t databytes[9] = {DATA_MODE, 0, 0, 0, 0, 0, 0, 0, 0};

  static char byte_count = 1;

  databytes[byte_count++] = qq;

  if ( byte_count > 8 ) { //8バイト分、貯まったら
    write_s(databytes, 9);
    byte_count = 1;
  } // endif

} //put8byte


//ドットを打つ
void Dot(int x, int y, uint8_t c) {

  static uint8_t qq = 0; //一時

  qq = qq | ( c << (y & 0x07));

  if ( (y & 0x07) == 7 ) { //1バイト分、貯まったら
    put8byte(qq); qq = 0; //SSD1306に出力
  }//end if

}//DOt


//キャラクターRAMの内容
char y_[] = {
  //1    2    3   4   5   6   7   8

    1 ,  2 ,  3 , 4 , 5 , 6 , 7 , 8  , //1
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //2 
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //3
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //4

    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //5
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //6 
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //7
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //8

    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //9
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //A 
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //B
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //C

    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //D
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //E 
    0 ,  0 ,  0 , 0 , 0 , 0 , 0 , 0  , //F
   56 , 57 , 58 ,59 ,60 ,61 ,62 ,63    //G

};


//再表示
void display(void) {

  char y; char x; char y1; char y2;

  //範囲の設定 (OLED内部のx,yカウンターを初期化してホームポジション0,0に)
  setPageAddress(0, MAX_PAGE);  // all pages
  setColumnAddress(0, MAX_COL); // all columns

  for (int ii = 0; ii < 8192; ii++) {

    //SSD1306のバッファーの配置順のxとyを求める
    //y =  ((ii & 0b0001110000000000 ) >> 7) + (ii & 0b0111);
    y2   =  (char)(ii       &     0b0111);
    if ( y2 == 0 ) {
      y1 =  (char)(ii >> 7) & 0b00111000;
      //x =   (ii & 0b0000001111111000)  >> 3;
      x = (char)(ii >> 3) & 0b1111111;
    }//endif y2
    y = y1 | y2;

    //↓開始　グラフのメイン処理 x=0...127 , y=0...64 
    if (y == y_[x]) {
      Dot(x, y, 1); //白のドットを打つ
    } else {
      Dot(x, y, 0); //黒のドットを打つ
    }//end if
    //↑終了

  }//for ii

}//display


//SSD1306の初期化
void display_begin(void) {

  //I2Cの初期化
  Wire.begin(); //M5Stamp S3
  delay(200);
  //Wire.setClock(2000000); //速度の変更 (I2C高速化 2Mhz) 493ms
  //Wire.setClock(1000000); //速度の変更 (I2C高速化 1Mhz) 125ms
  Wire.setClock(800000);  //速度の変更 (I2C高速化 800khz) 125ms
  //Wire.setClock(400000);  //速度の変更 (I2C高速化 400khz) 137ms
  //Wire.setClock(200000);  //速度の変更 (I2C高速化 200khz) 166ms
  //Wire.setClock(100000);  //速度の変更 (I2C高速化 100khz) 226ms
  delay(200);

  //SSD1306の初期化スペル(魔法)
  //0x80,0x8D,0x80,0x14,0x80,0xAF
  write_s( (uint8_t*) "\200\215\200\024\200\257", 6);
  delay(100);

  //セットメモリーアドレシングモード (画面の終端に来たら画面の先頭に)
  setMemoryAddressingMode();

  //セットディスプレー Flip (画面の向きを変える)
  setDisplayFlip(1, 0);

}//display_begin


//初期化
void setup() {

  //SSD1306の初期化
  display_begin();
  
}//setup


//メインループ
void loop() {

  y_[0]=1; //debug

  display(); //再表示
  delay(500); //0.5秒待つ

  //while(1){} //debug

  y_[0]=32; //debug

  display(); //再表示
  delay(500); //0.5秒待つ

}//loop



```