因為我們的目標是要能讓自製的 Ruby VM 運行在微控制器上並且在螢幕上顯示訊息,這次使用的是 TFT 螢幕型號是 ST7735
因為不同的硬體會有差異,在設定的時候需要特別注意連接的腳位跟設定值,如果跟我一樣使用的是復古遊戲機的話,配件都是相同的只需要確定能依照說明書上組裝並且運作即可。
會想要自己實作 Ruby VM 的原因之一就是我是有利用 mruby/c 嘗試在 ESP32 上面控制 TFT 螢幕,不過對硬體不熟悉加上沒有適合的專案可以參考所以一直都無法在 FreeRTOS 為基礎的 mruby/c 上面順利整合 TFT 螢幕顯示東西,也因此才會選擇自製一個簡單的 mruby 環境在 Arduino 的基礎下使用這些套件輔助,先把想法實現出來。
TFT_eSPI 是我自己嘗試過比較不會出問題的套件,同時也支援好幾種市面上能取得的螢幕,要使用這個套件可以透過 PlatformIO 的 lib_deps
選項追加。
; platformio.ini
; ...
[env:d1]
platform = espressif8266
board = d1
framework = arduino
custom_ruby_script = app.rb
build_flags = -D ESP8266
test_ignore = test_*
lib_deps =
TFT_eSPI
透過這個功能我們可以很輕鬆的取得 GitHub 上面的套件,不過微妙的是 PlatformIO 的審核機制非常微妙,自己製作的套件可以考慮直接透過 git
下載而不是先去 PlatformIO 上面登記會比較好。
詳細的用法可以參考文件,一般來說寫上 Git Repoistory 位置就能被自動下載。
除了下載套件之外,我們還需要針對螢幕進行設定。因為 TFT_eSPI 原本是針對 Arduino 的情境設計的,所以在 PlatformIO 上使用 Arduino 的處理方式會無法正確的設定螢幕,不過 TFT_eSPI 有針對 PlatformIO 加入支援可以透過 build_flags
來切換 TFT_eSPI 載入的設定。
以下是 ST7735
的設定,我們整合之前寫過的 -DESP8266
把他放到到剛剛加入的 lib_deps
的下面
; platformio.ini
; ...
build_flags =
-DESP8266
-Os
-DUSER_SETUP_LOADED=1
-DST7735_DRIVER=1
-DTFT_WIDTH=128
-DTFT_HEIGHT=160
# PIN configure
-DTFT_MISO=12
-DTFT_MOSI=13
-DTFT_SCLK=25
-DTFT_CS=15
-DTFT_DC=5
-DTFT_RST=-1
# Load Font
-DLOAD_GLCD=1
-DLOAD_FONT2=1
-DSPI_FREQUENCY=40000000
這些設定是參考復古遊戲機書上的說明所設定的,如果是不同的板子就會需要依照情況調整。
這些都設定好了之後,我們就可以修改 puts
方法將文字繪製到畫面上。
// src/main.c
#if defined(ESP8266)
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <SPI.h>
#endif
首先在 ESP8266 的狀況下將 TFT_eSPI.h
引入,這樣我們才能使用 TFT_eSPI
的功能。
// src/main.c
// ...
#if defined(ESP8266)
TFT_eSPI tft = TFT_eSPI();
#endif
void mrb_puts(mrb_state* mrb) {
int argc = mrb_get_argc(mrb);
mrb_value* argv = mrb_get_argv(mrb);
#if defined(ESP8266)
char num[4];
tft.fillScreen(TFT_BLACK);
#endif
for(int i = 0; i < argc; i++) {
printf("%d\n", mrb_fixnum(argv[i]));
#if defined(ESP8266)
sprintf(num, "%d", mrb_fixnum(argv[i]));
tft.drawString(num, 8, i * 16 + 8, 1);
#endif
}
}
接下來我們要對原本的 mrb_puts
做修改,只在 ESP8266 的狀態下啟用不同的功能,像是用 tft.fillScreen
清除畫面等等,不過最主要的是我們呼叫了 tft.drawString
把獲取到的數字繪製在畫面上。
最後要更新 setup
方法將 TFT 螢幕初始化,我們才能做後續的處理。
void setup() {
Serial.begin(9600);
tft.init();
tft.setTextSize(1);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
run_vm();
}
完成之後我們就可以用 pio run -e d1 -t upload
將程式碼上傳到開發版上,如果一切順利的話我們就可以看到呈現出來的畫面。
下一篇會討論一下 HAL 機制,讓我們將原始碼稍微重構來區分桌機跟開發版來避免現在這樣混在一起撰寫的狀況。