M5 AtomS3を動かしてみた

M5AtomS3が届いたので、さっそく動かしてみました。PlatformIOで動かしました。

https://www.switch-science.com/products/8670

# ハードウェア(最低限の情報)

MCU
　ESP32-S3FN8
IMU
　MPU6886
　I2C
　SDA：ポート38
　SCL：ポート39
LCD
　N085-1212TBWIG06-C08
　0.85インチ
　128x128
ボタン
　ポート41
赤外線出力(今回は使っていません)
　ポート4
Groveポート(今回は使っていません)
　ポート1、2

# 利用したライブラリ

LCDライブラリ(自動認識してくれました！）

https://github.com/lovyan03/LovyanGFX

MPU6886用IMUライブラリ

https://github.com/tanakamasayuki/I2C_MPU6886

ボタンライブラリ
　Arduinoライブラリから借用

# platformio.ini

すでにボード情報はあったので、それを使いました。

```ini:platformio.ini
[env:esp32-s3-devkitc-1]
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
monitor_speed = 115200
upload_port = COM3
monitor_port = COM3
lib_deps = 
	lovyan03/LovyanGFX@^0.5.0
	tanakamasayuki/I2C MPU6886 IMU@^1.0.0
```

# ソースコード

```cpp:main.cpp
#include <Arduino.h>
#define LGFX_AUTODETECT 
#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp>

static LGFX lcd; 

#include "I2C_MPU6886.h"
I2C_MPU6886 imu(I2C_MPU6886_DEFAULT_ADDRESS, Wire1);

#include "MyButton.h"
#define BUTTON_PORT 41
static MyButton Btn = MyButton(BUTTON_PORT, true, 10);

void setup() {
  // put your setup code here, to run once:

  USBSerial.begin(115200);

  USBSerial.println("Hello");

  lcd.init();
  lcd.fillScreen(0x000000u);

  Wire1.begin(38, 39);
  imu.begin();

  USBSerial.printf("whoAmI() = 0x%02x\n", imu.whoAmI());
}

void loop() {
  // put your main code here, to run repeatedly:

  static long counter = 0;
  static unsigned long start_tim = 0;

  Btn.read();

  bool pressed = Btn.wasPressed();
  if( pressed ){
    USBSerial.println("Btn Pressed");
  }

  unsigned long tim = millis();
  if( tim - start_tim < 1000)
    return;
  
  start_tim = tim;

  USBSerial.print("Hello ");
  USBSerial.println(counter);

  switch(++counter % 4){
    case 0: lcd.fillScreen(0x000000u); break;
    case 1: lcd.fillRect(20, 20, 20, 20, (uint8_t)0xE0); break;
    case 2: lcd.fillRect(30, 30, 20, 20, (uint8_t)0x1C); break;
    case 3: lcd.fillRect(40, 40, 20, 20, (uint8_t)0x03); break;
  }

  float ax, ay, az;
  float gx, gy, gz;
  float t;

  imu.getAccel(&ax, &ay, &az);
  imu.getGyro(&gx, &gy, &gz);
  imu.getTemp(&t);

  USBSerial.printf("%f, %f, %f, %f, %f, %f, %f\n", ax, ay, az, gx, gy, gz, t);

  delay(1);
}
```

ボタンライブラリ

```cpp:MyButton.cpp
/*----------------------------------------------------------------------*
 * Arduino Button Library v1.0                                          *
 * Jack Christensen May 2011, published Mar 2012                        *
 *                                                                      *
 * Library for reading momentary contact switches like tactile button   *
 * switches. Intended for use in state machine constructs.              *
 * Use the read() function to read all buttons in the main loop,        *
 * which should execute as fast as possible.                            *
 *                                                                      *
 * This work is licensed under the Creative Commons Attribution-        *
 * ShareAlike 3.0 Unported License. To view a copy of this license,     *
 * visit http://creativecommons.org/licenses/by-sa/3.0/ or send a       *
 * letter to Creative Commons, 171 Second Street, Suite 300,            *
 * San Francisco, California, 94105, USA.                               *
 *----------------------------------------------------------------------*/

#include "MyButton.h"

/*----------------------------------------------------------------------*
 * Button(pin, puEnable, invert, dbTime) instantiates a button object.  *
 * pin      Is the Arduino pin the button is connected to.              *
 * puEnable Enables the AVR internal pullup resistor if != 0 (can also  *
 *          use true or false).                                         *
 * invert   If invert == 0, interprets a high state as pressed, low as  *
 *          released. If invert != 0, interprets a high state as        *
 *          released, low as pressed  (can also use true or false).     *
 * dbTime   Is the debounce time in milliseconds.                       *
 *                                                                      *
 * (Note that invert cannot be implied from puEnable since an external  *
 *  pullup could be used.)                                              *
 *----------------------------------------------------------------------*/
MyButton::MyButton(uint8_t pin, uint8_t invert, uint32_t dbTime) {
    _pin    = pin;
    _invert = invert;
    _dbTime = dbTime;
    pinMode(_pin, INPUT_PULLUP);
    _state = digitalRead(_pin);
    if (_invert != 0) _state = !_state;
    _time       = millis();
    _lastState  = _state;
    _changed    = 0;
    _hold_time  = -1;
    _lastTime   = _time;
    _lastChange = _time;
    _pressTime  = _time;
}

/*----------------------------------------------------------------------*
 * read() returns the state of the button, 1==pressed, 0==released,     *
 * does debouncing, captures and maintains times, previous states, etc. *
 *----------------------------------------------------------------------*/
uint8_t MyButton::read(void) {
    static uint32_t ms;
    static uint8_t pinVal;

    ms     = millis();
    pinVal = digitalRead(_pin);
    if (_invert != 0) pinVal = !pinVal;
    if (ms - _lastChange < _dbTime) {
        _lastTime = _time;
        _time     = ms;
        _changed  = 0;
        return _state;
    } else {
        _lastTime  = _time;
        _time      = ms;
        _lastState = _state;
        _state     = pinVal;
        if (_state != _lastState) {
            _lastChange = ms;
            _changed    = 1;
            if (_state) {
                _pressTime = _time;
            }
        } else {
            _changed = 0;
        }
        return _state;
    }
}

/*----------------------------------------------------------------------*
 * isPressed() and isReleased() check the button state when it was last *
 * read, and return false (0) or true (!=0) accordingly.                *
 * These functions do not cause the button to be read.                  *
 *----------------------------------------------------------------------*/
uint8_t MyButton::isPressed(void) {
    return _state == 0 ? 0 : 1;
}

uint8_t MyButton::isReleased(void) {
    return _state == 0 ? 1 : 0;
}

/*----------------------------------------------------------------------*
 * wasPressed() and wasReleased() check the button state to see if it   *
 * changed between the last two reads and return false (0) or           *
 * true (!=0) accordingly.                                              *
 * These functions do not cause the button to be read.                  *
 *----------------------------------------------------------------------*/
uint8_t MyButton::wasPressed(void) {
    return _state && _changed;
}

uint8_t MyButton::wasReleased(void) {
    return !_state && _changed && millis() - _pressTime < _hold_time;
}

uint8_t MyButton::wasReleasefor(uint32_t ms) {
    _hold_time = ms;
    return !_state && _changed && millis() - _pressTime >= ms;
}
/*----------------------------------------------------------------------*
 * pressedFor(ms) and releasedFor(ms) check to see if the button is     *
 * pressed (or released), and has been in that state for the specified  *
 * time in milliseconds. Returns false (0) or true (1) accordingly.     *
 * These functions do not cause the button to be read.                  *
 *----------------------------------------------------------------------*/
uint8_t MyButton::pressedFor(uint32_t ms) {
    return (_state == 1 && _time - _lastChange >= ms) ? 1 : 0;
}

uint8_t MyButton::releasedFor(uint32_t ms) {
    return (_state == 0 && _time - _lastChange >= ms) ? 1 : 0;
}
/*----------------------------------------------------------------------*
 * lastChange() returns the time the button last changed state,         *
 * in milliseconds.                                                     *
 *----------------------------------------------------------------------*/
uint32_t MyButton::lastChange(void) {
    return _lastChange;
}
```

```h:MyButton.h
/*----------------------------------------------------------------------*
 * Arduino Button Library v1.0                                          *
 * Jack Christensen Mar 2012                                            *
 *                                                                      *
 * This work is licensed under the Creative Commons Attribution-        *
 * ShareAlike 3.0 Unported License. To view a copy of this license,     *
 * visit http://creativecommons.org/licenses/by-sa/3.0/ or send a       *
 * letter to Creative Commons, 171 Second Street, Suite 300,            *
 * San Francisco, California, 94105, USA.                               *
 *----------------------------------------------------------------------*/
#ifndef MyButton_h
#define MyButton_h
// #if ARDUINO >= 100
#include <Arduino.h>
// #else
// #include <WProgram.h>
// #endif
class MyButton {
   public:
    MyButton(uint8_t pin, uint8_t invert, uint32_t dbTime);
    uint8_t read();
    uint8_t isPressed();
    uint8_t isReleased();
    uint8_t wasPressed();
    uint8_t wasReleased();
    uint8_t pressedFor(uint32_t ms);
    uint8_t releasedFor(uint32_t ms);
    uint8_t wasReleasefor(uint32_t ms);
    uint32_t lastChange();

   private:
    uint8_t _pin;       // arduino pin number
    uint8_t _puEnable;  // internal pullup resistor enabled
    uint8_t _invert;    // if 0, interpret high state as pressed, else interpret
                        // low state as pressed
    uint8_t _state;     // current button state
    uint8_t _lastState;    // previous button state
    uint8_t _changed;      // state changed since last read
    uint32_t _time;        // time of current state (all times are in ms)
    uint32_t _lastTime;    // time of previous state
    uint32_t _lastChange;  // time of last state change
    uint32_t _dbTime;      // debounce time
    uint32_t _pressTime;   // press time
    uint32_t _hold_time;   // hold time call wasreleasefor
};
#endif
```

# 終わりに

正式なライブラリがPlatformIOに出てくるかと思いますが、それまでの応急処置です。

https://github.com/m5stack/M5AtomS3

参考
　[PlatformIOでのIniファイル指定例](https://qiita.com/poruruba/items/ef83e684df11439e259a)

以上