2016-02-18 AQM0802 library > v0.3 > add AQM0802_PutMessage()


http://qiita.com/7of9/items/c3c1acaf46822d7b2754
の続き

文字列を任意の位置に表示する関数を追加

```c
void AQM0802_PutMessage(String msg, uint8_t x_st1, uint8_t y_st1)
{
  // _st1 : index starting from 1
  if ((x_st1 > kMaxXsize) || (y_st1 > kMaxYsize)) {
    return; // error
  }

  uint8_t pos = 0x80 | ((y_st1 - 1) * 0x40);
  pos = pos | (x_st1 - 1);

  AQM0802_WriteSingleInstruction(pos);
  AQM0802_WriteData( (uint8_t *)msg.c_str(), msg.length() );  
}
```

## 準備手順

以下の準備を参照
http://qiita.com/7of9/items/c3c1acaf46822d7b2754


## code (v0.3)

```c:esp8266_160217_AQM0802.ino
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Serial.println("");  

  Wire.begin(); // (SDA,SCL) Default 4 and 5

  AQM0802_Initialize(/* cursorOn=*/true, /* cursorPosOn=*/true, /* contrast=*/7);
//  Test_AQM0802_cursorOn_posOff_contrastLow();
//  Test_AQM0802_cursorOn_posOn_contrastLow();
//  Test_AQM0802_cursorOn_posOn_contrastHigh();

  displayDateTime();
}

void displayDateTime()
{
  AQM0802_PutMessage("20160218", /* x_st1=*/1, /* y_st1=*/1);
  AQM0802_PutMessage("06:57", /* x_st1=*/3, /* y_st1=*/2);
  //Test_AQM0802_showDateTime("20160218", "06:57");
}

void loop() 
{
  static bool bfOn = true;

  if (bfOn) {
    displayDateTime();    
  } else{
    AQM0802_Clear();
  }

  bfOn = !(bfOn);

  delay(3000);
}
```

```c:AQM0802lib.ino
#include <Wire.h>

/*
 * v0.3 2016 Feb. 18
 *  - add message display function
 *    + add Test_AQM0802_showDateTime()
 *    + add AQM0802_PutMessage()
 * v0.2 2016 Feb. 17
 *  - add test functions()
 *    + add Test_AQM0802_cursorOn_posOn_contrastHigh()
 *    + add Test_AQM0802_cursorOn_posOn_contrastLow()
 *    + add Test_AQM0802_cursorOn_posOff_contrastLow()
 * v0.1 2016 Feb. 17
 *  - add AQM0802_Initialize()
 *  - add AQM0802_Clear()
 *  - add AQM0802_WriteData()
 *  - add AQM0802_WriteInstruction()
 *  - add writeToDevice()
 *
 * -------
 * Special thanks to exabugs for ( http://qiita.com/exabugs/items/9d1b66aa1d22805afbc8 )
 */

static const uint8_t kDeviceAddr = 0x3e;

static const int kMaxXsize = 8;
static const int kMaxYsize = 2;

static uint8_t ControlByteList[] = {
  0x00, // Instruction write operation. ( Co=0, Rs=0 )
  0x40, // Data write operation. ( Co=0, Rs=1 )
};

enum {
  TYPE_INSTRUCITON = 0,
  TYPE_DATA,
};

//---------------------------------------------------------------------------------

// private functions ---------------------------
void writeToDevice(int type, uint8_t *dataByte, size_t len) 
{
  for (int idx = 0; idx < len; idx++) {
    Wire.beginTransmission(kDeviceAddr);
    Wire.write(ControlByteList[type]);
    Wire.write(dataByte[idx]);
    Wire.endTransmission();
    delayMicroseconds(27); // 26.3us
  }
}

//---------------------------------------------------------------------------------

// public functions ---------------------------
void AQM0802_WriteSingleInstruction(uint8_t data) 
{ 
  size_t len = 1;
  uint8_t list[] = {data};
  writeToDevice(TYPE_INSTRUCITON, list, len); 
}

void AQM0802_WriteInstructions(uint8_t *data, int len) 
{ 
  writeToDevice(TYPE_INSTRUCITON, data, len); 
}

void AQM0802_WriteData(uint8_t *data, size_t len) 
{ 
  writeToDevice(TYPE_DATA, data, len); 
}

void AQM0802_Clear()
{
    AQM0802_WriteSingleInstruction(0x01);
}

void AQM0802_Initialize(bool cursorOn, bool cursorPosOn, uint8_t contrast)
{ 
  // 
  delay(40); // Wait time > 40ms after VDD stable

  // Function set
  AQM0802_WriteSingleInstruction(0x38);

  // Function set
  AQM0802_WriteSingleInstruction(0x39);

  // Internal OSC frequency
  AQM0802_WriteSingleInstruction(0x14);

  // { Contrast set -----------------------------
  uint8_t ctrst = contrast;
  if (ctrst > 0b1111) {
    ctrst = 0b1111;
  }
  AQM0802_WriteSingleInstruction(0x70 | ctrst);
  // } Contrast set -----------------------------

  // Power/ICON/Contrast control
  AQM0802_WriteSingleInstruction(0x56);

  // Follower control
  AQM0802_WriteSingleInstruction(0x6C);

  // Wait time > 200mS (for power stable)
  delay(200);

  // Function set
  AQM0802_WriteSingleInstruction(0x38);

  // { Display ON/OFF control -----------------------
  uint8_t extra = 0x0;
  if (cursorOn) {
    extra = extra | 0b10;
  }
  if (cursorPosOn) {
    extra = extra | 0b11;    
  }
  AQM0802_WriteSingleInstruction(0x0C | extra);
  // } Display ON/OFF control -----------------------

  // Clear Display
  AQM0802_WriteSingleInstruction(0x01);

  // Wait time > 1.08ms
  delay(2);
}

void AQM0802_PutMessage(String msg, uint8_t x_st1, uint8_t y_st1)
{
  // _st1 : index starting from 1
  if ((x_st1 > kMaxXsize) || (y_st1 > kMaxYsize)) {
    return; // error
  }

  uint8_t pos = 0x80 | ((y_st1 - 1) * 0x40);
  pos = pos | (x_st1 - 1);

  AQM0802_WriteSingleInstruction(pos);
  AQM0802_WriteData( (uint8_t *)msg.c_str(), msg.length() );  
}

//---------------------------------------------------------------------------------

// test functions ---------------------------

void Test_AQM0802_cursorOn_posOff_contrastLow()
{
  AQM0802_Initialize(/* cursorOn=*/true, /* cursorPosOn=*/false, /* contrast=*/1);
}

void Test_AQM0802_cursorOn_posOn_contrastLow()
{
  AQM0802_Initialize(/* cursorOn=*/true, /* cursorPosOn=*/true, /* contrast=*/1);
}

void Test_AQM0802_cursorOn_posOn_contrastHigh()
{
  AQM0802_Initialize(/* cursorOn=*/true, /* cursorPosOn=*/true, /* contrast=*/15);
}

void Test_AQM0802_showDateTime(String datstr, String timstr)
{
  AQM0802_PutMessage(datstr, /* x_st1=*/1, /* y_st1=*/1);
  AQM0802_PutMessage(timstr, /* x_st1=*/3, /* y_st1=*/2);
}
```

## 動作

3秒おきに以下の A または B を実行する。

- A. 日時の表示
- B. 画面クリア

![DSC_0099.JPG](https://qiita-image-store.s3.amazonaws.com/0/32870/b7d34af3-cc61-bb8e-5928-f2aed6e247ed.jpeg)

![DSC_0100.JPG](https://qiita-image-store.s3.amazonaws.com/0/32870/7d1449f2-65c1-7099-f50f-70306bedb865.jpeg)



## 備考

メッセージのWrap機能はまだつけてない。

(未検証だが、そのままWrapされるかもしれない。アドレスの計算を考えて)

(追記 2016/02/20)
確認したところ、Wrapは自動ではされない。
文字あふれ時にWrapする処理に変更が必要。