
まず言って置きます。LazuriteのI2Cの標準の速度は400kHzだぁ。つまずく事間違いなし。勿論私もつまづいた!
※setupの中で100kHzに落としてねー!
さて今日のお題はArudinoとかGR-KURUMIとか用に作成したライブラリの移植の話。
LazuriteはC++をサポートしていないので、ライブラリは全てCソースで記述しなければならない。
この辺を参照して欲しい。
http://hamayan.blog.so-net.ne.jp/2016-10-17
つまりArduinoのライブラリを持って来てもコンパイルすら通らないので、地道にコツコツCソースへの置き換えが必要となる。きっとここでめげる人多数、、、
とは言え買っちゃったのでなんとか使いこなす必要性から、なんとかしてみたいと思う。
今回移植するライブラリはGR-KURUMI用に作成したOLED表示器のライブラリです。
※ArduinoのライブラリをGR-KURUMIに持ってきた場合、かなりの確率でそのまま動く。修正が必要となったとしても、それ程手間ではない。
以下にGR-KURUMI用のソースを掲載します。
US2066.cpp ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/*********************************************************************************/ /* US2066を使用したOLED SO1602AWGBの初期化と表示 */ /* designed by hamayan since 2015/04/21 */ /*********************************************************************************/ #include <RLduino78.h> #include <iodefine.h> #include <iodefine_ext.h> #include <US2066.h> extern "C" { #include <mul_tsk.h> } #if !defined( _MULTITASK_H_ ) #define dly_tsk(tim) delay(tim) #define rot_rdq() #define loc_cpu() interrupts() #define unl_cpu() noInterrupts() #endif /*_MULTITASK_H_ */ US2066::US2066() { } /****************************************************************************/ /* I2C block Write */ /****************************************************************************/ int US2066::blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len) { Wire.beginTransmission(addr); Wire.write(dat,len); return Wire.endTransmission(); } /*************************************************************************/ /* write command */ /*************************************************************************/ int US2066::writeCommand(unsigned char t_command) { unsigned char cmd[2]; cmd[0] = 0x00; cmd[1] = t_command; return blkWrite( i2cAddress, cmd, sizeof(cmd) ); } /*************************************************************************/ /* write data */ /*************************************************************************/ int US2066::writeData(unsigned char t_data) { unsigned char dat[2]; dat[0] = 0x40; dat[1] = t_data; return blkWrite( i2cAddress, dat, sizeof(dat) ); } /*************************************************************************/ /* US2066初期化 */ /*************************************************************************/ void US2066::init( unsigned char adr ) { i2cAddress = adr; /*I2C address set*/ dly_tsk(100); writeCommand( 0x01 ); //clear display dly_tsk(20); writeCommand( 0x02 ); //return home dly_tsk(2); writeCommand( 0x0f ); //send display on command dly_tsk(2); writeCommand( 0x01 ); //clear display dly_tsk(20); } /*************************************************************************/ /* clear display */ /*************************************************************************/ void US2066::clear( void ) { dly_tsk(100); writeCommand( 0x01 ); //clear display dly_tsk(20); } /*************************************************************************/ /* display on/off */ /*************************************************************************/ void US2066::OnOff( unsigned char onoff ) { writeCommand( onoff | 0x08 ); //display on/off,cursor on/off,blink on/off dly_tsk(20); } /*************************************************************************/ /* locate */ /*************************************************************************/ void US2066::locate( int x, int y ) { int temp = x + (y * 20); if(temp >= 20) temp = (temp - 20) + 0x20; writeCommand( (unsigned char)temp | 0x80 ); //set ddram address dly_tsk(20); } /*************************************************************************/ /* set contrast */ /*************************************************************************/ void US2066::contrast( unsigned char cnt ) { //コントラスト調整 writeCommand( 0x2a ); //RE=1 writeCommand( 0x79 ); //SD=1 writeCommand( 0x81 ); //contrast set writeCommand( cnt ); //contrast max writeCommand( 0x78 ); //SD=0 writeCommand( 0x28 ); //set character size is normal. dly_tsk(100); } /*************************************************************************/ /* write strings */ /*************************************************************************/ int US2066::writeString( const char *str ) { unsigned char dat[1 * SO2002A_COLUMN + 1]; int len = strlen(str); dat[0] = 0x40; len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len; memcpy( &dat[1], str, len ); return blkWrite( i2cAddress, dat, len + 1 ); } /*************************************************************************/ /* write strings */ /*************************************************************************/ int US2066::writeString( const char *str, unsigned int len ) { unsigned char dat[1 * SO2002A_COLUMN + 1]; dat[0] = 0x40; len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len; memcpy( &dat[1], str, len ); return blkWrite( i2cAddress, dat, len + 1 ); } /*************************************************************************/ /* write strings */ /*************************************************************************/ int US2066::writeString( String str ) { return writeString( (const char *)&str[0], str.length() ); } /*********************************************************************************/ /* end of file */ /*********************************************************************************/
US2066.h ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/****************************************************************************/ /* ssd1305 header */ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/ #ifndef US2066_h #define US2066_h #include <wire.h> extern "C" { } //#define US2066_0_ADR 0x3C #define SO2002A_LINES 2 #define SO2002A_COLUMN 16 #define SO2002A_DISPLAY_ON 0x04 #define SO2002A_DISPLAY_OFF 0x00 #define SO2002A_CURSOR_ON 0x02 #define SO2002A_CURSOR_OFF 0x00 #define SO2002A_BLINK_ON 0x01 #define SO2002A_BLINK_OFF 0x00 class US2066 { private: unsigned char i2cAddress; int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len); int writeCommand(unsigned char t_command); int writeData(unsigned char t_data); public: US2066(); void init( unsigned char adr ); void clear( void ); void OnOff( unsigned char onoff ); void locate( int x, int y ); void contrast( unsigned char cnt ); int writeString( const char *str ); int writeString( const char *str, unsigned int len ); int writeString( String str ); }; #endif /*US2066_H*/ /****************************************************************************/ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/
さてこれを移植するのですが、まずC++の記述スタイルはCには適用できない事が多い!
例えば関数のオーバーライド
int writeString( const char *str ); int writeString( const char *str, unsigned int len ); int writeString( String str );
なんてもろにダメですね!
Wire.endTransmission();
こう言った省略もダメです。
まぁ実際にコンパイル掛けてみると色々エラーや警告出ますんで、一つ一つ潰していくしかない。
クラスのメッソッドっぽく記述し直す必要があります。例えば
US2066 oled; oled.init( 10 );
みたいに書きたいとすれば、関数名のリストを作った構造体を用意して、それで呼び出す事になります。
結局以下の様になりました。
US2066.c ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/*********************************************************************************/ /* US2066を使用したOLED SO1602AWGBの初期化と表示 */ /* designed by hamayan since 2015/04/21 */ /*********************************************************************************/ #include <US2066.h> #if !defined( _MULTITASK_H_ ) #define dly_tsk(tim) delay(tim) #define rot_rdq() #define loc_cpu() interrupts() #define unl_cpu() noInterrupts() #endif /*_MULTITASK_H_ */ static unsigned char i2cAddress; static int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len); static int writeCommand(unsigned char t_command); static int writeData(unsigned char t_data); /****************************************************************************/ /* I2C block Write */ /****************************************************************************/ static int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len) { Wire.beginTransmission(addr); Wire.write(dat,len); return Wire.endTransmission( true ); } /*************************************************************************/ /* write command */ /*************************************************************************/ static int writeCommand(unsigned char t_command) { unsigned char cmd[2]; cmd[0] = 0x00; cmd[1] = t_command; return blkWrite( i2cAddress, cmd, sizeof(cmd) ); } /*************************************************************************/ /* write data */ /*************************************************************************/ static int writeData(unsigned char t_data) { unsigned char dat[2]; dat[0] = 0x40; dat[1] = t_data; return blkWrite( i2cAddress, dat, sizeof(dat) ); } /*************************************************************************/ /* US2066初期化 */ /*************************************************************************/ static void init( unsigned char adr ) { i2cAddress = adr; /*I2C address set*/ dly_tsk(100); writeCommand( 0x01 ); //clear display dly_tsk(20); writeCommand( 0x02 ); //return home dly_tsk(2); writeCommand( 0x0f ); //send display on command dly_tsk(2); writeCommand( 0x01 ); //clear display dly_tsk(20); } /*************************************************************************/ /* clear display */ /*************************************************************************/ static void clear( void ) { dly_tsk(100); writeCommand( 0x01 ); //clear display dly_tsk(20); } /*************************************************************************/ /* display on/off */ /*************************************************************************/ static void OnOff( unsigned char onoff ) { writeCommand( onoff | (unsigned char)0x08 ); //display on/off,cursor on/off,blink on/off dly_tsk(20); } /*************************************************************************/ /* locate */ /*************************************************************************/ static void locate( int x, int y ) { int temp = x + (y * 20); if(temp >= 20) temp = (temp - 20) + 0x20; writeCommand( (unsigned char)temp | (unsigned char)0x80 ); //set ddram address dly_tsk(20); } /*************************************************************************/ /* set contrast */ /*************************************************************************/ static void contrast( unsigned char cnt ) { //コントラスト調整 writeCommand( 0x2a ); //RE=1 writeCommand( 0x79 ); //SD=1 writeCommand( 0x81 ); //contrast set writeCommand( cnt ); //contrast max writeCommand( 0x78 ); //SD=0 writeCommand( 0x28 ); //set character size is normal. dly_tsk(100); } /*************************************************************************/ /* write strings */ /*************************************************************************/ static int writeString( const char *str ) { unsigned char dat[1 * SO2002A_COLUMN + 1]; int len = strlen(str); dat[0] = 0x40; len = (len > sizeof(dat) - 1) ? sizeof(dat) - 1 : len; memcpy( &dat[1], str, len ); return blkWrite( i2cAddress, dat, len + 1 ); } /*************************************************************************/ /* メンバー関数のリスト */ /*************************************************************************/ const t_US2066_I2C oled = { init, clear, OnOff, locate, contrast, writeString, }; /*********************************************************************************/ /* end of file */ /*********************************************************************************/
US2066.h ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
/****************************************************************************/ /* ssd1305 header */ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/ #ifndef US2066_h #define US2066_h #include <Wire.h> //#define US2066_0_ADR 0x3C #define SO2002A_LINES 2 #define SO2002A_COLUMN 16 #define SO2002A_DISPLAY_ON 0x04 #define SO2002A_DISPLAY_OFF 0x00 #define SO2002A_CURSOR_ON 0x02 #define SO2002A_CURSOR_OFF 0x00 #define SO2002A_BLINK_ON 0x01 #define SO2002A_BLINK_OFF 0x00 #if 0 class US2066 { private: unsigned char i2cAddress; int blkWrite(unsigned char addr, const unsigned char *dat, unsigned int len); int writeCommand(unsigned char t_command); int writeData(unsigned char t_data); public: US2066(); void init( unsigned char adr ); void clear( void ); void OnOff( unsigned char onoff ); void locate( int x, int y ); void contrast( unsigned char cnt ); int writeString( const char *str ); int writeString( const char *str, unsigned int len ); int writeString( String str ); }; #else typedef struct { void (*init)( unsigned char adr ); void (*clear)( void ); void (*OnOff)( unsigned char onoff ); void (*locate)( int x, int y ); void (*contrast)( unsigned char cnt ); int (*writeString)( const char *str ); } t_US2066_I2C; extern const t_US2066_I2C oled; #endif #endif /*US2066_H*/ /****************************************************************************/ /* Copyright (C) 2014 hamayan All Rights Reserved. */ /****************************************************************************/
※関数のオーバーライドの代替関数はめんどうくさいので止めちゃいました!
※BME280の移植をしていて気付いたのですが、long long型が使えない、、、
上記ソースを、Lazurite IDEが入っているフォルダーの中のlibraries以下に、ソースと同じ名前にしたフォルダーを生成し、そこに収納します。

この状態でIDEを起動するとこのライブラリが左端のライブラリリストに表示されますので、チェックします。
※I2CなのでWireにもチェックを入れます。

で、冒頭の表示プログラムが以下になります。
blue_led.c ※<とか>などhtmlに変換した時に正しく変換されていない可能性が有るので、使わない事。
#include "blue_led_ide.h" // Additional Header #include "mcu.h" #define BLUE_LED 26 #define US2066_ADDRESS (0x3C << 0) void setup(void) { digitalWrite(BLUE_LED,HIGH); pinMode(BLUE_LED,OUTPUT); Wire.begin(); I21MD=0; /*100khz setup*/ oled.init( US2066_ADDRESS ); oled.contrast( 0xff ); oled.clear(); oled.OnOff( SO2002A_DISPLAY_ON | SO2002A_CURSOR_OFF | SO2002A_BLINK_OFF ); oled.writeString( "Lazurite 920J" ); oled.locate( 0, 1 ); oled.writeString( " with OLED" ); } void loop(void) { digitalWrite(BLUE_LED,HIGH); delay(1000); digitalWrite(BLUE_LED,LOW); delay(1000); }
冒頭でmcu.hをインクルードしていますが、I2Cの速度を落とす為に必要です。
またsetupの先頭の
Wire.begin(); I21MD=0; /*100khz setup*/
も必要です。
※まぁこれくらいのコード量なら移植はそれほどでもですが、もっと複雑なコードだと厳しいですね。BME280の移植はそれなりに手間でしたよ。
※IDEのライブラリにBME280は登録されていますが、、、SPIで動かした時のライブラリで、I2Cではありませんでしたorz。
※いや、最大の問題はこんなライブラリの移植ではなく、フォーラムのレスポンスの悪さだったりして。