M5AtomS3のCirquitPython対応過程の記録

こちら、本家マージされました。新規にボード対応される方やCircuitPythonのESP32あたりでハマられている方のご参考になればと思います。

完成〜
![274483272-2ac5c76b-2dcb-42c3-b2e7-bfd18906b356.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103775/0244bdd7-ec8b-91e3-bbc7-5a4288033bc6.jpeg)

### 現在の状態

- 本家マージ済み（CircuitPython9以降で含まれています）
- Functional
    - BOARDの基本PIN設定
    - DISPLAY
    - WIFI
    - IMU(https://github.com/tkomde/Circuitpython_MPU6886)
- Not Functional
    - BLE: セントラルロールとアドバタイズはできるようなのですが、ペリフェラルをやろうとしてサービスを作成あたりでNotImplementedと表示されます。これはhttps://learn.adafruit.com/welcome-to-circuitpython/frequently-asked-questions#faq-3129409 の状況のようで、ESP32全般同様です。ペリフェラルが動かないのでBLEワークフローも動きません。

ちなみに手持ちで Seeed Studio Xiao ESP32S3 のイメージも無かったので調べたら[このような](https://github.com/adafruit/circuitpython/pull/8095)状況のようです。[Seeed公式からESP32-S3-DevKitC-1-N8を使う方法](https://wiki.seeedstudio.com/XIAO_ESP32S3_CircuitPython/)がアナウンスされています。

### Circuitpythonを自分でビルドする簡単な技

adafruit/circuitpythonのレポジトリはgithub codespacesに対応しているので、普通にちょっとボード対応するだけの場合はこちらの技が良いです。

https://adafruit-playground.com/u/picofun/pages/using-github-codespaces-for-circuitpython-development

### Circuitpythonを自分でビルドするための環境設定

ローカルに環境作ってビルドする場合はこんな感じになります。

#### 初回

Pythonの仮想環境の関係で以下の順番で実施してください

```
git clone xxx (後々PRする気がある場合はforkしておく)
cd circuitpython
make fetch-tags # forkした場合に必要

# Fetch Submodules (espressifだけビルドする場合、ディレクトリに移動して、部分インストール)
cd ports/espressif
make fetch-port-submodules

# esp-idfのインストール
esp-idf/install.sh

# esp-idfの環境設定
source esp-idf/export.sh

# ここでPython依存関係インストール
cd ../..
pip3 install --upgrade -r requirements-dev.txt
pip3 install --upgrade -r requirements-doc.txt
cd -

# make
make BOARD=m5stack_atoms3
make BOARD=seeed_xiao_esp32s3
```

pyelftools,clickのバージョンがおかしいと言われたらバージョン落とす。

#### 二回目以降

二回目以降、ビルドするターミナルで環境変数読み込みを毎回実行します。

```
cd circuitpython/ports/espressif
source esp-idf/export.sh

# その階層のまま make
make BOARD=m5stack_atoms3
make BOARD=seeed_xiao_esp32s3
```

#### シリアルコンソール繋がらない問題

- MuEditorだと安定している
- Terminalでscreen（screen /dev/tty.usbmodemCD45570D99431 115200）
- VSCode で以下をやると直るという噂も（But not solved,,）
    - https://github.com/joedevivo/vscode-circuitpython/issues/103
    - cd /Users/{User}/.vscode/extensions/joedevivo.vscode-circuitpython-0.1.20-darwin-x64/boards/0x303A
    - cp -a 0x8114 0x8120

### 調査段階でのメモ

#### circuitpythonのファームウェアインストール

circuitpythonの通常の方法は **オフィシャルのWebサイトからWeb Serialを使ってインストール** ですが、AtomS3はオフィシャルイメージが無いのと、近いであろうS3LiteだとオフィシャルのWebインストーラーがこけるので以下のどちらかの方法を取ります。

##### 方法その１

通常のcircuitpythonフローでファームウェアを更新するために [Tiny UF2](https://github.com/adafruit/tinyuf2/releases) を使用します。

4つのbinを[Adafruit_WebSerial_ESPTool](https://adafruit.github.io/Adafruit_WebSerial_ESPTool/)もしくはesptoolで書き込みます。esptoolだと以下で、Webで書き込む場合はファイルの指定と開始位置をスクリプトと合わせてください。

esptool.py --chip esp32s3 -p /dev/cu.usbmodem111101 --before=default_reset --after=no_reset write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 bootloader.bin 0x8000 partition-table.bin 0xe000 ota_data_initial.bin 0x410000 tinyuf2.bin

ユーザーボタン（M5AtomS3の場合は液晶ボタン）押しながらリセット押すかケーブル挿すとATOMS3BOOTというフォルダが見えるようになり、この状態でUF2をコピーするとファームウェアが更新できます。

##### 方法その2

Bootモードでシリアルで書き込みます。

- CIUCUITPYとして認識されている場合はアンマウントします
- リセット長押し（緑LEDチカする）
- [Adafruit_WebSerial_ESPTool](https://adafruit.github.io/Adafruit_WebSerial_ESPTool/)もしくはesptool で書き込む
    - UF2ではなく.binを書き込む(自分でビルドした場合はfirmware.binのほうで、circuitpython-firmware.binではないので注意)
- 単押でリセット

#### AtomS3 Liteのファームで試してみた結果

```
print(dir(board))
AtomS3 Liteだと以下しか定義されていない（SPI系のピンが定義なし）
['__class__', '__name__', 'A1', 'A2', 'A4', 'A5', 'A6', 'A7', 'BTN', 'D1', 'D2', 'D38', 'D39', 'D5', 'D6', 'D7', 'D8', 'I2C', 'IR_LED', 'NEOPIXEL', 'PORTA_I2C', 'PORTA_SCL', 'PORTA_SDA', 'board_id']
```

このコードは動いた
```
import time
import board
from digitalio import DigitalInOut, Direction, Pull

#PIN情報取得
print(dir(board))

btn = DigitalInOut(board.BTN)
btn.direction = Direction.INPUT
btn.pull = Pull.UP

while True:
    if not btn.value:
        print("BTN is down")
    else:
        #print("BTN is up")#押した時だけ反応
        pass

    time.sleep(0.1) # sleep for debounce
```

S3LiteになくてS3にあるLCD(SPI)、IMUを追加して、存在しないNEOPIXELは削ったものを作れば良い

StickCのほうが近いかも（ディスプレイがST7735S、IMUもあるし。ただUSBストレージにできないのと、BLEのモジュールは含まれていない）

https://docs.m5stack.com/en/core/m5stickc
GPIO15	　GPIO13　	GPIO23	GPIO18	GPIO5
TFT_MOSI TFT_CLK	TFT_DC	TFT_RST	TFT_CS

https://docs.m5stack.com/en/core/AtomS3
GPIO21	　GPIO17　	GPIO33	GPIO34	GPIO15
TFT_MOSI TFT_CLK	TFT_DC	TFT_RST	TFT_CS
GPIO16はBL

StickCを真似るならここ見る
https://github.com/adafruit/circuitpython/blob/main/ports/espressif/boards/m5stack_stick_c

StickCはDisplayを自前で初期化しているっぽい（ST7735Sのドライバを読み込んでいるわけではない）

GC9107はST7789互換だけど微妙に初期化が違う
https://qiita.com/kitazaki/items/3be1014022bd5f5c20ce

IDF_TARGET がESP32、ESP32S3とかがある。ESP32だとなぜかcircuitpythonだと_bleioモジュールがビルドされない（ESP32S2ってターゲットはまた別にある、ビルドサイズが大きくなってROMに入らなくなるので外した？？）。

Atom Lite, Stick-CとかはESP-PICOだけどESP32が指定されていてcircuitpythonのオフィシャルビルド（8.2.6）だとESP32が指定されているせいで_bleioが入ってない。

ESP32-C3のほうはサイズの関係でBLE外されてしまったっぽい、、