mBlock が生成した「Hello World」のソースは、こういう感じでした。
#include <Arduino.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include "watchX.h"
#include <SPI.h>
double angle_rad = PI/180.0;
double angle_deg = 180.0/PI;
unsigned char animation_offsetY=0;
bool needClear = false;
void writeText(int oledPosX, int oledPosY, String oledText){
drawString(oledPosX,oledPosY,oledText.c_str() ,smallFont);}
void setup(){
SPI.begin();
ssd1306_configure();
clearAll();
writeText(0, 0, ((String)"Hello World!").c_str());
needClear = true;
}
void loop(){
_loop();
}
void _delay(float seconds){
long endTime = millis() + seconds * 1000;
while(millis() < endTime)_loop();
}
void _loop(){
if(needClear){
ssd1306_drawBuffer(0, 0, 128,64, mbuf);
clearAll();
needClear = false;
}
}
内容を確認してみます。
#include <Arduino.h> #include <Wire.h> #include <SoftwareSerial.h> #include "watchX.h" #include <SPI.h>
通常の Arduino 系 include に加えて、”watchX.h”ヘッダーがあります。
watchX.h
#include "Adafruit_Sensor.h" #include "Adafruit_BMP280.h" #include "SparkFun_MAG3110.h" #include "RTClib.h" #include "MPU6050.h" #include "oled.h" #include "resources.h" #include "Adafruit_BLE.h" #include "Adafruit_BluefruitLE_SPI.h" #include "Adafruit_BluefruitLE_UART.h" #include "BluefruitConfig.h"
ライブラリ関連のincludeをまとめて行ってますね。
setup() の処理を見ると、
ssd1306_configure();
で watchX 表示関連の初期化を行っているみたいです。ssd1306_configure() は、oled.cpp にあります。
void ssd1306_configure(){
const uint8_t s_oled128x64_initData[] =
{
SSD1306_DISPLAYOFF, // display off
SSD1306_MEMORYMODE, HORIZONTAL_ADDRESSING_MODE, // Page Addressing mode
SSD1306_COMSCANDEC, // Scan from 127 to 0 (Reverse scan)
SSD1306_SETSTARTLINE | 0x00, // First line to start scanning from
SSD1306_SETCONTRAST, 0xFF, // contast value to 0x7F according to datasheet
SSD1306_SEGREMAP | 0x01, // Use reverse mapping. 0x00 - is normal mapping
SSD1306_NORMALDISPLAY,
SSD1306_SETMULTIPLEX, 63, // Reset to default MUX. See datasheet
// SSD1306_SETDISPLAYOFFSET, 0x00, // no offset
// SSD1306_SETDISPLAYCLOCKDIV, 0x80,// set to default ratio/osc frequency
// SSD1306_SETPRECHARGE, 0xF1, // switch precharge to 0x22 // 0xF1
// SSD1306_SETCOMPINS, 0x12, // set divide ratio
SSD1306_SETVCOMDETECT, 0x40, // vcom deselect to 0x20 // 0x40
SSD1306_CHARGEPUMP, 0x14, // Enable charge pump
// 0X20,0X80,
// SSD1306_DISPLAYALLON_RESUME,
SSD1306_DISPLAYON
};
pinMode(rstPin, OUTPUT);
pinMode(cesPin, OUTPUT);
pinMode(dcPin, OUTPUT);
digitalWrite(rstPin, HIGH);
digitalWrite(dcPin, HIGH);
digitalWrite(cesPin, HIGH);
for( uint8_t i=0; i<sizeof(s_oled128x64_initData); i++)
{
ssd1306_sendCommand(s_oled128x64_initData[i]);
}
}
ピンの状態を設定して、初期設定のコマンドを順に ssd1306_sendCommand で送ってます。
次が clearAll();
void clearAll(){
//if(animation_offsetY==0)
memset(mbuf, 0x00, 1024);
//for(uint16_t i=0;i<1024;i++) mbuf[i]=0;
}
mbuf[1024]が、画面表示のバッファです。0クリアしてます。
次の
writeText(0, 0, ((String)"Hello World!").c_str());
が、”Hello World!” を バッファに書き込んでいるところです。
drawString(oledPosX,oledPosY,oledText.c_str() ,smallFont);
を(フォントの指定を追加して)呼び出してます。実際の処理は oled.cpp 内のdrawString。
void drawString(uint8_t x,uint8_t y,const char*s,const char* font,char startindex=-32);
void drawString(uint8_t x,uint8_t y,const char*s,const char* font,char startindex){
char a=0;
if(!s)return;
while(s[a]!=0){
// strtmpbuf[a]= pgm_read_byte_near(months[month]+a);
// draw_bitmap( 0, 32, font_mid, 19, 24, false, 0);
draw_bitmap( x+(a*6), y, font+((s[a]+startindex)*5), 5, 8, false, 0);
a++;
}
}
位置(x,y)から、文字列char* s それぞれ順番に、フォント char*font を用いて描きます。
startIndexはフォント文字コードとフォントデータの開始位置調整です。なにもなければデフォルトで指定されている「-32」が使われてます。文字コードの制御文字コードの部分を飛ばすためですね。
1文字描くごとに、x 位置を 6 ずつずらしています。(完全にフォントサイズ固定な処理ですね。)
font+((s[a]+startindex)*5)で、フォントデータの開始位置。これも1フォントのデータ5バイト固定想定での実装です。
フォントデータは,resources.h の CHARACTER_SET 経由で、english.h にありました。
#define CHARACTER_SET \ 0x00,0x00,0x00,0x00,0x00,/* space */ \ 0x00,0x5F,0x00,0x00,0x00,/* ! */ \ 0x00,0x07,0x00,0x07,0x00,/* " */ \ 0x14,0x7F,0x14,0x7F,0x14,/* # */ \ 0x24,0x2A,0x7F,0x2A,0x12,/* $ */ \ 0x23,0x13,0x08,0x64,0x62,/* % */ \ 0x36,0x49,0x55,0x22,0x50,/* & */ \ 0x00,0x05,0x03,0x00,0x00,/* ' */ \ 0x1C,0x22,0x41,0x00,0x00,/* ( */ \ 0x41,0x22,0x1C,0x00,0x00,/* ) */ \ : 0x3E,0x51,0x49,0x45,0x3E,/* 0 */ \ 0x00,0x42,0x7F,0x40,0x00,/* 1 */ \ 0x62,0x51,0x49,0x49,0x46,/* 2 */ \ 0x22,0x41,0x49,0x49,0x36,/* 3 */ \ 0x18,0x14,0x12,0x7F,0x10,/* 4 */ \ 0x27,0x45,0x45,0x45,0x39,/* 5 */ \ 0x3C,0x4A,0x49,0x49,0x30,/* 6 */ \ 0x01,0x71,0x09,0x05,0x03,/* 7 */ \ 0x36,0x49,0x49,0x49,0x36,/* 8 */ \ 0x06,0x49,0x49,0x29,0x1E,/* 9 */ \ : 0x7E,0x09,0x09,0x09,0x7E,/* A */ \ 0x7F,0x49,0x49,0x49,0x36,/* B */ \ 0x3E,0x41,0x41,0x41,0x22,/* C */ \ 0x7F,0x41,0x41,0x22,0x1C,/* D */ \ 0x7F,0x49,0x49,0x49,0x41,/* E */ \ 0x7F,0x09,0x09,0x09,0x01,/* F */ \ 0x3E,0x41,0x41,0x51,0x72,/* G */ \ :
という感じ。例えば
0x7E,0x09,0x09,0x09,0x7E,/* A */ \
を16進→2進 変換してみると…
7E : 01111110 09 : 00001001 09 : 00001001 09 : 00001001 7E : 01111110
んんんー?「A」の形にならない…。と思ったら、縦向きに描かれるらしい。
漢字表示グラフィック液晶表示ライブラリ
http://www.picfun.com/PIC32MX/PIC32MXAp05.html
こういうことか!
このデータを
void draw_bitmap(byte x, byte yy, const char* bitmap, byte w, byte h, bool invert=false, byte offsetY=0);
で画面表示バッファmbuf に設定してます。中身の処理は追っかけないですけども、x , yy + offsetY の位置に、bitmap で指定したフォントデータを、幅 w 高さ h でセットするようですね。invert = true にすると、白黒反転すると思われます。
その後、loop() の中で、
ssd1306_drawBuffer(0, 0, 128,64, mbuf);
実際の画面に mbuf 内容を描画して、
clearAll();
で描画が終了した mbuf をクリアして、終了な感じですね。(実際は loop()を回ってますけども。)
フォントは縦横回転してしまうフォーマットなので、M5Stack の時に作ったデータはそのままでは使えないなあー。
