LCDモジュール ACM1602NI(I2C接続) を制御するライブラリ

Dependents:   scan2 BoxController

Revision:
0:c7da9183f23a
Child:
9:96baac039a90
diff -r 000000000000 -r c7da9183f23a LcdAcm1602ni.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LcdAcm1602ni.cpp	Wed Dec 14 03:48:13 2016 +0000
@@ -0,0 +1,318 @@
+/** LCDモジュール ACM1602NI を制御するクラスの定義
+*/
+#include "LcdAcm1602ni.h"
+
+const uint8_t    LcdAcm1602ni::LINE_HEAD_ADDR_TBL[LINE_COUNT] = {0x00, 0x40};     //!< 行の先頭アドレス
+    
+/** コンストラクタ
+*/
+LcdAcm1602ni::LcdAcm1602ni(PinName pinSDA, PinName pinSCL)
+    :m_pinSDA(pinSDA)
+    ,m_pinSCL(pinSCL)
+    ,m_i2c(pinSDA, pinSCL)
+    ,m_currentLineNo(0)
+    ,m_currentCharaNo(0)
+    ,m_displayVisible(true)
+    ,m_cursorVisible(false)
+    ,m_blinkEnable(false)
+{
+}
+/** デストラクタ
+*/
+LcdAcm1602ni::~LcdAcm1602ni()
+{
+}
+
+
+/** 初期化
+*/
+void LcdAcm1602ni::initialize()
+{
+    // I2C通信の周波数設定
+    m_i2c.frequency(I2C_MAX_FREQUENCY);
+
+    uint8_t command;
+    
+    // ディスプレイを消す
+    command = calcDisplayControlByteData(false, false, false);
+    writeCommand(command);
+    wait_us(53);
+    
+    // ファンクション設定(0011[8bitモード]1[2行モード]0[文字5x8表示モー]00 = 00111000 = 0x38)
+    writeCommand(0x38);
+    wait_us(53);
+    
+    // 画面クリア(00000001 = 0x01)
+    writeCommand(0x01);
+    wait_us(2160);
+    
+    // データ書き込み後アドレス加算モード設定(0000011[インクリメント]0 = 00000110 = 0x06)
+    writeCommand(0x06);
+    wait_us(53);
+    
+    // ディスプレイ表示
+    command = calcDisplayControlByteData();
+    writeCommand(command);
+    wait_us(53);
+
+}
+
+
+/** 1文字描画
+*/
+void LcdAcm1602ni::putc(char c)
+{
+    // 1文字書き込み
+    writeData(c);
+    // カーソル位置管理処理
+    bool ret = incCursorPos();
+    if (ret) {
+        // 復帰・改行が発生したのでカーソル位置変更
+        uint8_t addr = calcCursorAddr(m_currentLineNo, m_currentCharaNo);
+        writeCommand(0x80 | addr);
+    }
+}
+/** 文字列描画
+*/
+void LcdAcm1602ni::puts(const char* pStr)
+{
+    uint8_t addr;
+    bool ret;
+    const char* pt = pStr;
+    bool stayLocate = false;
+    while (*pt) {
+        const char &c = *pt;
+        if (c == '\r') {
+            // 復帰コードの場合、行の先頭にカーソルを移動する
+            m_currentCharaNo = 0;
+            // 実際の移動処理は後で行う
+            stayLocate = true;
+        }
+        else if (c == '\n') {
+            // 改行コードの場合、次の行にカーソルを移動する
+            m_currentLineNo = (m_currentLineNo + 1) % LINE_COUNT;
+            // 実際の移動処理は後で行う
+            stayLocate = true;
+        }
+        else {
+            // 通常の文字コードの場合
+            if (stayLocate) {
+                // 復帰・改行の予約がある場合は先に処理
+                addr = calcCursorAddr(m_currentLineNo, m_currentCharaNo);
+                writeCommand(0x80 | addr);
+                stayLocate = false;
+            }
+            // 1文字書き込み
+            writeData(c);
+            // カーソル位置管理処理
+            ret = incCursorPos();
+            if (ret) {
+                // 改行が発生したのでカーソル位置変更
+                // 実際の移動処理は後で行う
+                stayLocate = true;
+            }
+        }
+        pt++;
+    }
+    if (stayLocate) {
+        // 復帰・改行の予約が残っている場合は処理する
+        addr = calcCursorAddr(m_currentLineNo, m_currentCharaNo);
+        writeCommand(0x80 | addr);
+    }
+}
+/** フォーマット指定描画
+*/
+void LcdAcm1602ni::printf(const char* pFormat, ...)
+{
+    va_list ap;
+    va_start(ap, pFormat);
+    char* allocatedBuffer;
+    int size = vasprintf(&allocatedBuffer, pFormat, ap);
+    va_end(ap);
+    puts(allocatedBuffer);
+    free(allocatedBuffer);
+}
+
+
+/** カーソル位置変更
+*/
+void LcdAcm1602ni::locate(uint8_t lineNo, uint8_t charaNo)
+{
+    if (lineNo >= LINE_COUNT) lineNo = LINE_COUNT - 1;
+    if (charaNo >= LINE_CHARA_COUNT) charaNo = LINE_CHARA_COUNT - 1;
+    m_currentLineNo = lineNo;
+    m_currentCharaNo = charaNo;
+    uint8_t addr = calcCursorAddr(m_currentLineNo, m_currentCharaNo);
+    writeCommand(0x80 | addr);
+}
+/** カーソル位置取得:行番号
+*/
+uint8_t LcdAcm1602ni::getCurrentLineNo() const
+{
+    return m_currentLineNo;
+}
+/** カーソル位置取得:文字番号
+*/
+uint8_t LcdAcm1602ni::getCurrentCharaNo() const
+{
+    return m_currentCharaNo;
+}
+
+
+/** 画面クリア
+*/
+void LcdAcm1602ni::clearDisplay()
+{
+    writeCommand(0x01);
+    wait_us(2160);
+}
+/** 行クリア
+*/
+void LcdAcm1602ni::clearLine(uint8_t lineNo)
+{
+    if (lineNo >= LINE_COUNT) return;
+    
+    // クリアする行の先頭に移動
+    uint8_t addr = calcCursorAddr(lineNo, 0);
+    writeCommand(0x80 | addr);
+    // 1行全体に' '書き込み
+    for (uint8_t i = 0; i < LINE_CHARA_COUNT; i++) {
+        writeData(' ');
+    }
+    // カーソル位置をクリアした行の先頭に移動
+    m_currentLineNo = lineNo;
+    m_currentCharaNo = 0;
+    addr = calcCursorAddr(m_currentLineNo, m_currentCharaNo);
+    writeCommand(0x80 | addr);
+}
+/** 範囲クリア
+*/
+void LcdAcm1602ni::clearRange(uint8_t startLineNo, uint8_t startCharaNo, uint8_t endLineNo, uint8_t endCharaNo)
+{
+    if (startLineNo >= LINE_COUNT) return;
+    if (startCharaNo >= LINE_CHARA_COUNT) return;
+    if (startLineNo > endLineNo) return;
+    if (startCharaNo > endCharaNo) return;
+    if (endLineNo >= LINE_COUNT) endLineNo = LINE_COUNT - 1;
+    if (endCharaNo >= LINE_CHARA_COUNT) endCharaNo = LINE_CHARA_COUNT - 1;
+
+    uint8_t addr;
+    for (uint8_t lineNo = startLineNo; lineNo <= endLineNo; lineNo++) {
+        // 対象行の削除開始位置にカーソル移動
+        addr = calcCursorAddr(lineNo, startCharaNo);
+        writeCommand(0x80 | addr);
+        // 消す範囲に' 'を書き込み
+        for (uint8_t charaNo = startCharaNo; charaNo <= endCharaNo; charaNo++) {
+            writeData(' ');
+        }
+    }
+    // クリアした範囲の開始位置にカーソルを移動
+    m_currentLineNo = startLineNo;
+    m_currentCharaNo = startCharaNo;
+    addr = calcCursorAddr(m_currentLineNo, m_currentCharaNo);
+    writeCommand(0x80 | addr);
+}
+
+
+/** 画面の表示設定
+*/
+void LcdAcm1602ni::setDisplayVisible(bool visible)
+{
+    if (m_displayVisible == visible) return;
+    m_displayVisible = visible;
+    uint8_t command = calcDisplayControlByteData();
+    writeCommand(command);
+}
+/** 画面の表示設定取得
+*/
+bool LcdAcm1602ni::getDisplayVisible() const
+{
+    return m_displayVisible;
+}
+/** カーソルの表示設定
+*/
+void LcdAcm1602ni::setCursorVisible(bool visible)
+{
+    if (m_cursorVisible == visible) return;
+    m_cursorVisible = visible;
+    uint8_t command = calcDisplayControlByteData();
+    writeCommand(command);
+}
+/** カーソルの表示設定取得
+*/
+bool LcdAcm1602ni::getCursorVisible() const
+{
+    return m_cursorVisible;
+}
+/** カーソルの点滅設定
+*/
+void LcdAcm1602ni::setBlinkEnable(bool enable)
+{
+    if (m_blinkEnable == enable) return;
+    m_blinkEnable = enable;
+    uint8_t command = calcDisplayControlByteData();
+    writeCommand(command);
+}
+/** カーソルの点滅設定取得
+*/
+bool LcdAcm1602ni::getBlinkEnable() const
+{
+    return m_blinkEnable;
+}
+
+
+/** LCDコマンド書き込み
+*/
+void LcdAcm1602ni::writeCommand(uint8_t commandByte)
+{
+    m_i2c.start();
+    m_i2c.write(ADDR_BYTE_WRITE);
+    m_i2c.write(CTRL_BYTE_COMMAND);
+    m_i2c.write(commandByte);
+    m_i2c.stop();
+}
+/** LCDデータ書き込み
+*/
+void LcdAcm1602ni::writeData(uint8_t  dataByte)
+{
+    m_i2c.start();
+    m_i2c.write(ADDR_BYTE_WRITE);
+    m_i2c.write(CTRL_BYTE_DATA);
+    m_i2c.write(dataByte);
+    m_i2c.stop();
+}
+
+
+/** ディスプレイ制御コマンド指定バイトデータの生成
+*/
+uint8_t LcdAcm1602ni::calcDisplayControlByteData(bool displayVisible, bool cursorVisible, bool blinkEnable) const
+{
+    uint8_t byteData = 0x08;
+    if (displayVisible) byteData |= 0x04;
+    if (cursorVisible)  byteData |= 0x02;
+    if (blinkEnable)    byteData |= 0x01;
+    return byteData;
+}
+
+
+/** カーソル位置移動管理
+*/
+bool LcdAcm1602ni::incCursorPos()
+{
+    m_currentCharaNo++;
+    if (m_currentCharaNo >= LINE_CHARA_COUNT) {
+        m_currentCharaNo = 0;
+        m_currentLineNo = (m_currentLineNo + 1) % LINE_COUNT;
+        return true;
+    }
+    return false;
+}
+
+
+/** カーソル位置のアドレス計算
+*/
+uint8_t LcdAcm1602ni::calcCursorAddr(uint8_t lineNo, uint8_t charaNo)
+{
+    uint8_t addr = LINE_HEAD_ADDR_TBL[lineNo] + charaNo;
+    return addr;
+}