Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for M5Stack M5Paper #8293

Merged
merged 4 commits into from
Aug 28, 2023
Merged

Conversation

fonix232
Copy link

@fonix232 fonix232 commented Aug 17, 2023

Fixes #8290

Current status:

  1. Brought over initial state from M5Stack-Fire (which is the same approach used by M5Stack in their sources published for the M5Paper)
  2. Assigned pins manually, without any A/D/GPIO pin naming assignment, purely just functions (this will most likely need to be expanded)
  3. Named and grouped pins based on function, and (mostly) in incremental order, except for where the grouping didn't make it possible (PORT A and PORT B definitions)
  4. Added (commented out) display init code

Things left to do:

  1. Adding display init (and possibly stop and refresh) sequences, or, depending on the displayio implementation, completely foregoing that subsystem in favour of a custom driver (the whole IT8951 source code is a mess 😞 )
  2. Adding the GT911 (touchscreen) driver
  3. Adding the BM8563 (RTC) driver and setup/init
  4. Adding the power management system (easy access to turn the MAIN and EXT and EPD power MOSFETs on and off)
  5. Adding support for the FM24C02 CMOS/NVRAM
  6. Adding support for the SHT30 temperature and humidity sensor
  7. Anything else pointed out (probably better pin definitions to begin with)

@fonix232
Copy link
Author

Not sure what's going on with the pygamer target - I didn't really touch any code that could affect it, with the localisation POT being the main exception.

@dhalbert
Copy link
Collaborator

pygamer ja translation is 44 bytes too large. Your message addition should have been localized to your board, hmm.

@fonix232
Copy link
Author

@dhalbert I was following the automated pre-commit patch for that update - anything I can do to fix it?

Also, could you take a look at the pins to see if there's any further addition needed? The M5Paper is quite limited in exposed pins, and they're all part of the typical M5Stack A/B/C ports, so I'm not sure if there's any point in adding the analog/digital/touch pin definitions.

@dhalbert
Copy link
Collaborator

@fonix232 Don't worry about the pygamer failure. We will fix that later. We can merge without it.

I'm not sure if there's any point in adding the analog/digital/touch pin definitions.

These are the _INT pins? Can they be used at all? Are the pins connected to anything? If they aren't, no reason to add them.

@fonix232
Copy link
Author

fonix232 commented Aug 21, 2023

@dhalbert PortA/PortB/PortC pins are available externally through 4-pin Molex connectors (5V, GND, plus the two pins of the port as per pins.h). The other pins I've defined, such as the internal SPI (pins 12, 13, 14), the additional SPI pins used by the e-ink display controller IT8951 (pins 15, 23, 27), or the MOSFET hookup pins for power control (pin 5 for controlling power to the external ports, pin 23 for controlling the MOSFET supplying power to the IT8951 chip which also acts as reset, and pin 2 for main power - I'll be pushing a fix for these pin names momentarily). No pins outside the PortA/PortB/PortC are available to the user.

_INT pins are interrupt pins (although there's only one being used, by the touchscreen).

Edit: I shouldn't be commenting before my morning coffee. So just to clarify:

There are in total SIX pins available for the user to access: pins 18 and 19 (used for UART by default), pins 26 and 33 (used as GPIO), and pins 25 and 32 (used as I2C). These can be reconfigured for any supported function of the ESP32.

@fonix232
Copy link
Author

Oh also @dhalbert one more question - since this device comes with some integrated features (display, touchscreen, BMS, SHT3x sensor set, RTC controller, etc.), including some that require mandatory pre-init (e.g. pulling up pin 2 on boot to enable the main power rails)... Is there a way in CircuitPython to make an abstract instance of these features available?

I'm guessing that I could make the power-related init sequences part of board_init(void), but how would I e.g. add a generic touchscreen instance to the board object? Also how about drivers for the various features, where would those reside?

@dhalbert
Copy link
Collaborator

For the onboard I2C devices like SHT, touch, RTC, is there a separate on-board I2C bus, or is it shared with external pins? You can make multiple I2C buses that appear in board. See separate board.I2C() and board.STEMMA_I2C() in say QT Py RP2040.

But we don't provide board. instances for specific I2C devices.

Some folks with highly integrated boards or educational boards add board-specific libraries, sometimes frozen, sometimes not. You could do that if you want. CPX is our only example, and we only did that to get around the limited RAM of CPX. CPB does not freeze anything.

@fonix232
Copy link
Author

@dhalbert the internal I2C bus is on pins sda:21 scl:22 - the external I2C is on pins sda:25 scl:32.

I've tried to be descriptive with the naming, as you can see GPIO25 is assigned to the PORTA_SDA name, and GPIO32 is to PORTA_SCL (and similarly the UART external port pins are named PORTC_RX and PORTC_TX).

For internals, I just relied on the standard naming of SDA and SCL for I2C, and MOSI, MISO, SCK for SPI (with the e-ink controller getting the IT8951_CS, IT8951_RESET and IT8951_BUSY pin names, plus SD_CS for the SD card's chip select).

Pardon my ignorance but what are CPX and CPB?

I've also looked into the QTPy board, but aside from a generic I2C, SPI and UART definition, I'm not seeing where the pin values are assigned:

{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },

or are &board_i2c_obj, &board_spi_obj and &board_uart_obj object created automatically, using the standard naming format (e.g. &board_i2c_obj will automatically assign the pins labeled MP_ROM_QSTR(MP_QSTR_SDA) and MP_ROM_QSTR(MP_QSTR_SCL))?

@dhalbert
Copy link
Collaborator

dhalbert commented Aug 21, 2023

The STEMMA_I2C object here is a second I2C bus:

{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_stemma_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },

The two buses are created here, with their pins specified. Note the (2):
#define CIRCUITPY_BOARD_I2C (2)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO6, .sda = &pin_GPIO7}, \
{.scl = &pin_GPIO40, .sda = &pin_GPIO41}}

The extra singleton for board.STEMMA_I2C is defined at the top of pins.c. The 1 is a subscript for the second entry from the mpconfigboard.h definition above. The two definitions are [0] and [1].
CIRCUITPY_BOARD_BUS_SINGLETON(stemma_i2c, i2c, 1)

@dhalbert
Copy link
Collaborator

CPX and CPB are Circuit Playground Express (SAMD21) and Circuit Playground Bluefruit (nRF52840) -- sorry!

@fonix232
Copy link
Author

Brilliant, thanks @dhalbert. I'll be pushing the changes to reflect these details soon.

Also thanks for pointing me at the CPX/CPB boards, the way frozen libraries are handled is really straightforward now that I see an example. I think the best way forward would be to add the necessary drivers to a separate repo, and add that as a submodule, then finally add them as frozen modules to this board. I understand that this wouldn't necessarily be the preferred way of doing things, but since this is a regular ESP32 board, a similar issue to the CPX's memory problem pops up - the harder management due to having no true USB interface. Therefore I think bundling the drivers frozen is the best option we have for full support.

Is there a project template I could follow for the frozen libraries? Also, how about incorporating native C/C++ code in these modules? Most of the M5EPD code, even the ported bits for other platforms, is in C++, and with my level of knowledge I don't feel 100% safe rewriting those drivers (or maintaining them!). Fortunately most of the protocols are pretty standard and by the book.

@fonix232 fonix232 marked this pull request as ready for review August 22, 2023 14:14
Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fine to me. Do you have more changes you want to add before merging?

@fonix232
Copy link
Author

@tannewt shall I remove the commented out init sequence for the EPD? The IT8951E driver is quite complex (and the M5Paper has some weirdness about bringing up the SPI bus, apparently at init it needs to be low speed, around 1MHz, then later ramped up to 10-20MHz), and I'm not sure I'll have the time to port it. Also, since apparently the REPL is pushed to the main display (based on the Waveshare ESP32-S2-Pico-LCD I got, which does so), I'm not sure if it's wise to have the display assigned to the board itself (EPD can't really keep up with the speed of the REPL).

@tannewt
Copy link
Member

tannewt commented Aug 24, 2023

Totally fine to leave it out until you have time to add it. Folks can always do it from user Python code too.

@fonix232
Copy link
Author

In that case, if you don't mind, let's leave the commented out code as-is, it might be a good future pointer for anyone who wants to implement it.

Which means it's ready to merge 🙂

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FR] Add support for M5Paper (and variations)
3 participants