LCDモジュール ACM1602NI(I2C接続) を制御するライブラリ
Dependents: scan2 BoxController
Diff: LcdAcm1602ni.cpp
- Revision:
- 0:c7da9183f23a
- Child:
- 9:96baac039a90
--- /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; +}