Library for LCD ACM1602NI connected using I2C interface on Nucleo F401/411. Nucleo F401/411RE で使える I2C 接続の LCD ACM1602NI 用のライブラリ.

Dependents:   ACM1602NI_NucleoF4_Demo ACM1602NI_NucleoF4_Demo

ACM1602NI.cpp

Committer:
CQpub0Mikami
Date:
2014-12-14
Revision:
3:8e405cedea99
Parent:
2:56a2f5e674e4

File content as of revision 3:8e405cedea99:

//-------------------------------------------------------
//  Class for LCD, ACM1602Ni
//
//  2014/12/14, Copyright (c) 2014 MIKAMI, Naoki
//-------------------------------------------------------

#include "ACM1602NI.hpp"

namespace Mikami
{
    // Constructor
    Acm1602Ni::Acm1602Ni(PinName sda, PinName scl, uint32_t clock,
                         bool cursor, bool blink)
        : i2c_(sda, scl), myI2c_((I2C_TypeDef*)NULL)
    {
        if ( ((sda == PB_9) || (sda == PB_7)) &&
             ((scl == PB_8) || (scl == PB_6)) )
                myI2c_ = (I2C_TypeDef*)I2C_1;   // I2C1 will be used
        if ( (sda == PB_3) && (scl == PB_10) )
                myI2c_ = (I2C_TypeDef*)I2C_2;   // I2C2 will be used
        if ( ((sda == PC_9) || (sda == PB_4)) &&
             (scl == PA_8) )
                myI2c_ = (I2C_TypeDef*)I2C_3;   // I2C3 will be used
        
        connected_ = Clear();      // Clear display
        if (!connected_)
        {
            fprintf(stderr, "\r\nLCD device not connected\r\n");
            return;
        }
        if (clock != 100000) i2c_.frequency(clock);

        WriteCmd(0x38); // data length:8-bit, 2-line, 5×8 dots
        WriteCmd(0x0C | (cursor << 1) | blink);
        WriteCmd(0x06); // cursor direction: rightward
    }

    // All clear
    bool Acm1602Ni::Clear()
    {
        bool ok = WriteCmd(0x01);
        wait_ms(50);
        return ok;
    }

    // Write string
    void Acm1602Ni::WriteString(const char str[])
    {
        for (int n=0; n<16; n++)
            if (str[n] == 0) break;
            else             WriteChar(str[n]);
    }

    // Write string from specified position
    void Acm1602Ni::WriteStringXY(const char str[],
                                uint8_t x, uint8_t y)
    {
        SetXY(x, y);
        WriteString(str);
    }

    //---------------------------------------------------
    // Following functions: private

    // Send command and data
    bool Acm1602Ni::LcdTx(uint8_t cmdData, uint8_t data)
    {
        if (!Start()) return false;
        // defines kind of "data" in next statement
        TxDR(cmdData);
        TxDR(data);
        wait_us(500);   // indispensable
        // Generate stop condition
        SetCR1(I2C_CR1_STOP);
        return true;
    }

    // Preparation for send of command and data
    bool Acm1602Ni::Start()
    {
        const uint8_t WAIT = 30;
        const uint8_t LENGTH = 10;

        // wait for I2C not busy
        for (int n=0; n<LENGTH; n++)
        {
            wait_us(WAIT);      
            if (!CheckSR2(I2C_SR2_BUSY)) break;
            if (n == LENGTH-1) return false;
        }

        // Generate start condition
        SetCR1(I2C_CR1_START);
        // Confirm start condition and master mode
        for (int n=0; n<LENGTH; n++)
        {
            wait_us(WAIT);
            if (CheckSR12(I2C_SR1_SB, I2C_SR2_MSL |
                                      I2C_SR2_BUSY)) break;
            if (n == LENGTH-1) return false;
        }

        // Send slave address
        TxDR(LCD_ADDRESS_);
        // Confirm on transmit mode
        for (int n=0; n<LENGTH; n++)
        {
            wait_us(WAIT);      
            if (CheckSR12(I2C_SR1_TXE | I2C_SR1_ADDR,
                          I2C_SR2_MSL | I2C_SR2_BUSY
                                      | I2C_SR2_TRA)) break;
            if (n == LENGTH-1) return false;
        }

        return true;
    }
}