前言:

話說筆者的 FORTH,是在高中的時候,那時候好不容易弄到一台 Apple ][ ,然後弄到一片 MircoMotion FORTH-79 的磁碟片,就學起 FORTH 語言來囉。

印象深刻的是, FORTH 不只是語言而已,也是個類似 DOS 的作業系統。 FORTH 裡面有簡單的實作了磁片的驅動,所以可以任意的以 FORTH 的方式讀取磁片上的磁區。採用絕對定址的方式,它把磁片上的磁區每 1024 byte 分成一塊,叫做 Block 的。你可以透過這個指令,以絕對定址的方式存取磁片上的任何一個 Block。 (例如: 0 Block, 1 Block, 2 Block ...)

以 Block 為基礎,它也提供了 Block 編輯器。也就是說,程式碼不是用檔案的方式來儲存的,而是以明碼字串的方式,存在一塊塊的 Block 裡面。 FORTH 的發明人Chunk Moore 認為「Simple is the power」,用 Block 來取代作業系統中複雜的檔案結構,才是最簡單,最有效率,也最有威力的方法。

(例如,虛擬記憶體,虛擬陣列... 這些很容易用 Block 來實作並漂亮地嵌入到你的程式之中。)

所以經典 FORTH 系統中,編輯 Block 裡頭文字的區塊編輯器 Block Editor,被用來編輯跟撰寫儲存 FORTH 的程式碼,一直是絕對不可或缺的角色。

雖然 FORTH 裡面的 Block 非常的有威力,但是慢慢地,慢慢地,世界並不是只有 FORTH 這種語言的。隨著各種作業系統及圖形介面環境的興起,愈來越多的各種語言跟應用程式都離不開作業系統跟其掌控的圖形介面跟各式的檔案處理。雖然經典的 FORTH 不需要任何的作業系統,也可以自己活得很好。但是你的 PC 裡面,FORTH 慢慢不會是唯一的主角,而是作業系統的核心掌控了一切。所以雖然新世代的 FORTH 系統, block 還是存在的,但大家還是習慣使用作業系統的檔案管理來管理跟編輯程式碼。所以漸漸的,能編輯文字的 Block Editor 就漸漸沒人在用囉。

但對於 ESP32FORTH 這種迷你的系統而言, 在完全不依賴外部電腦的情況下,經典 FORTH 特有的區塊編輯器 Block Editor,無疑的依舊是最佳的選擇之一。

所以來一篇 EPS32FORTH 區塊編輯器 Block Editor 的介紹吧。 讓我們來利用它,在不借助任何外部電腦的情況下,只靠 ESP32 來編輯並儲存我們的程式碼,並且直接在 ESP32 上面編譯跟執行。

同時來測試一下 ESP32 的 GPIO 吧,來測試一下最基本的利用 digital I/O 來控制 LED 的閃滅!

 

ESP32FORTH 區塊編輯器

對一般 FORTH 而言,磁碟空間上 1024 bytes (1K bytes) 的大小被稱作一個區塊 (block)。

1024 = 16 * 64 = 16 列 x 64 行

所以等於 16列,每列 64行的 總共 1024 字元的單 byte 文字。

ESP32FORTH 把檔案的的空間分成一個一個大小為 1024 bytes 的 Block,編號從0開始,並提供 Block Editor 區塊編輯器來編輯每個 Block 裡面的文字。

先來介紹一下第一個指令

 

list ( n --)  

輸入 block 編號,然後列印裡面的內容

 

例如,

0 list 會列印第 0 block 的內容出來, 1 list 會列印第 1 block 的內容出來。

範例

鍵入 0 list 及 1 list ,分別將第 1, 2 block 的內容印出來

list example.png

可以看到首先 'Block' 後面接著 Block 的號碼,

接下來就是 16列, 64 行的文字。 為了方便辨識,最右邊 0, 1, 2 ... 15 是列號碼,方便定位文字列的位置。

這個範例可以看得很清楚,Block 0 有了一小段 Blinking 指令的定義,而 Block 1 是完全空的!

來,我們來使用 Block Editor 吧,

Block Editor 的指令放在 Editor 的詞彙中。對 FORTH 不熟悉的,來介紹一下, FORTH 不只是只有 word 指令詞而已。因為很多指令都擠在一起,很大機會會重複到,這樣就打架囉。所以 FORTH 的指令,還有"詞彙" vocabulary 這一層。我們會利用詞彙 vocabulary 來一群一群的管理我們的指令。

正常沒有特殊指名的話,我們都在 'FORTH' 這個詞彙下定義指令跟搜尋指令。 Block Editor 的指令都放在 'Editor' 的這個詞彙,所以我們會搜尋不到,也無法執行。

所以要使用 Block Editor 前,須先鍵入 editor,告訴系統,現在請在 Editor 詞彙裡面搜尋指令,這樣我們才找得到。

先打 order 指令,它可告訴你,你現在在 FORTH 詞彙中

再打 editor 指令,把 editor 詞彙放到搜尋的頭。可以用 order 指令確認,現在 editor 詞彙會先被搜尋,然後才是 FORTH 詞彙

利用 vlist 指令,和 words 不同,它只會把現在第一位的詞彙裡面的指令顯示出來。

editor words.png

所以在 Editor 詞彙裡面,我們有 a r d e wipe p n l 這幾個區塊編輯器的指令,一一解釋如下

 

wipe ( --)

將 scr 變數所指的現用的 block ,將 block 裡面的內容清空。我們 FORTH 系統裡面有個叫做 scr 的變數,一旦你有用過 list 來列印 block 內容時,那個最後一次的那個 block 會被放到 scr 變數裡面當作現用的 block!

我們用這個指令來清除掉目前現用 block 的內容。

L ( --)

將現用 block 的內容列印出來, 它其實就是 scr @ list

d ( n --)

在現用的 block 裡面,刪除第 n 列的資料。然後下面那列會補上來。

e ( n --)

在現用的 block 裡面,清除第 n 列的資料。就直接清空留給你一列空白列,下面那列不會補上來。

r ( n "text" --)

將 r 後面的文字一直到換行字元為止,放入現用的 block 裡面的第 n 列。如果這個列原來已經有內容的話將會被取代,這個會是區塊編輯器的主要的文字輸入指令。

a ( n "text" --)

將 a 後面的文字一直到換行字元為止,插入現用的 block 裡面的第 n 列。而下面的所有列將會往下推,這個也會是區塊編輯器的主要的文字輸入指令。

p ( --)

移動到上一個 block

n ( --)

移動到下一個 block

 

再來,還要介紹很重要的兩個指令

 

flush ( --)

將現用的 block 的內容從記憶體裡面存入非揮發記憶體中。這相當於電腦裡的 Save。我們用區塊編輯器做了很多文字的修改,就像使用 MS Word 一樣,這一切都發生在電腦的記憶體裡面,只要一關機就完全消失囉。唯有當你說 Save (flush) 的時候,這些內容才會真的被存入非揮發記憶體中永久保存。這也給你反悔的機會,假如你覺得這次的修改不太好,只要不下 flush,基本上資料就不會被寫入保存的啦。

 

load ( n --)

用來編譯用的啦,會把第 n block的內容取出,然後逐行編譯到 forth 的字典裡面。

 

來,跟我練習一下你就熟悉囉。來讓我們在 block 0 輸入一下 LED 閃滅的程式碼吧!

 

0 list

wipe

0 r ( LED blinking test 2022.07.01 )

1 r : blinking  ( --)

2 r    18 output pinMode

3 r    begin   18 high digitalWrite   500 ms

4 r            18 low  digitalWrite   500 ms

5 r   again 

6 r ;

 

來確認一下

0 list

滿意的話,

flush

存入非揮發記憶體裡面。

想要編譯這段內容,簡單啦,就

0 load

就進來囉。

這裡要小小說明的,雖然我們在這裡稱呼這個叫做區塊編輯器 Block Editor。但在以前,還是有點小小分別的。現在你所看到的這種逐行編輯,用指令來運作的編輯器,有人叫做列編輯器 Line Editor。真正的區塊編輯器應該像Vi或 Vim 一樣,有游標在文字間移動,然後使用者下指令來插入或刪除文字。

FORTH 有個好處,不滿意,你可以自己改啊。不管是列編輯器還是區塊編輯器,你可以自己用 FORTH 寫個更棒的進來,沒人會限制你。

 

ESP32FORTH GPIO 測試

來試試看 ESP32 的 GPIO 吧,

放上 ESP32 WROOM 32U 的外觀圖

esp32 wroom 32u.jpeg

 

它的 GPIO Pinout

esp32 wroom 32u pinout.jpeg

要注意的, 5V 旁邊那個腳位是 CMD 啊,不是 GND 啊。

錯接了可是會發生可怕的事情的喲。

 

然後 ESP32 本身是 3.3V 的 MCU,跟 Arduino UNO 的 Atmega328 不一樣,不是 5V 的喲。

所以 GPIO High 的輸出,也是 3.3V 的喲!

 

由 Pinout 的圖,我們選用 Pin18 來接限流電阻,然後接上 LED 的正極 (長腳), LED 的負極(短腳)接地

限流電阻,因為紅光 LED 二極體順向偏壓會吃掉大概 2.1V 的電壓。假如我們大概要 5mA 電流的亮度,所以需要的限流電阻大小為 (3.3 - 2.1)V / 5mA = 240 ohm, 所以我們選 220 ohm (紅紅棕)這顆。

簡單如下圖,

IMG_9145.png

 

ESP32 跟 Arduino IDE 是完全相容的,所以要使用 GPIO,

1. 第一步先設定 GPIO 的方向,

看是要讀取還是要寫入,指令跟 Arduino 一樣,

輸出: pinMode(<pin>, OUTPUT), 輸入: pinMode(<pin>, INPUT)

對應到 ESP32FORTH

輸出: <pin> OUTPUT pinMode, 輸入: <pin> INPUT pinMode

所以要把 pin18 設成輸出的指令為

18 output pinMode

 

2. 第二步先控制 GPIO 的讀或寫,

跟 Arduino 一樣

讀取: digitalRead(<pin>), 寫入 digitalWrite(<pin>, HIGH/LOW)

對應到 ESP32FORTH

讀取: <pin> digitalRead, 寫入 <pin> high/low digitalWrite

所以要把 pin18 設成輸出 high 的指令為

18 high digitalWrite

設成輸出 low 的指令為

18 low digitalWrite

 

再來是 delay 多少毫秒 (ms) 的指令,正常在 Arduino 裡面我們用 delay(<ms>) 的指令。

但是在標準 FORTH 的標準裡面,我們用 ms 這個指令。所以 ESP32FORTH 使用 ms 這個指令來做 delay 多少毫秒 (ms)

 

所以 LED 閃滅,

就一個 begin-again 的無窮迴圈, 18 high digitalWrite 讓第 18 pin 變成 high 3.3V, 500 ms 延遲個 0.5 秒後, 18 low digitalWrite 讓第 18 pin 變成 low 0V 關掉 LED,再 500 ms 延遲個 0.5 秒後,如此週而復始。

測試很順利, LED 每亮 0.5秒後就滅 0.5秒,週而復始永不停止。

 

原始程式碼列表,

( LED blinking test 2022.07.01 )
: blinking  ( --)
   18 output pinMode
   begin   18 high digitalWrite   500 ms
           18 low  digitalWrite   500 ms
   again
;

 

 

 

xxx

 

 

 

arrow
arrow

    ohiyooo2 發表在 痞客邦 留言(0) 人氣()