ALXV Labs Byte90
Byte90
The Byte90 is a development board based on the ESP32-S3 module, featuring a USB-C connector, a color 128x128 OLED, a button, and an ADXL345 accelerometer, all in a little housing that makes it look like a retro computer (e.g. C64, ZX Spectrum).
See the Byte90 product page for more information.
The espp::Byte90 component provides a singleton hardware abstraction for initializing the various subsystems.
API Reference
Header File
Classes
-
class Byte90 : public espp::BaseComponent
The Byte90 class provides an interface to the Byte90 ESP32-S3 development board.
The class provides access to the following features:
The class is a singleton and can be accessed using the get() method.
For more information, see https://github.com/alxv2016/Byte90-alxvlabs
**Pin Reference Table:**
| XIAO Pin | GPIO | Function | Component | |———-|——|———-|———–| | D0 | GPIO1 | RST | Display Reset | | D1 | GPIO2 | INT | ADXL345 Interrupt | | A3 | GPIO4 | INPUT | Button (with pull-up) | | D4 | GPIO5 | SDA | ADXL345 I2C Data | | D5 | GPIO6 | SCL | ADXL345 I2C Clock | | D8 | GPIO7 | SCK | Display SPI Clock | | D10 | GPIO9 | MOSI | Display SPI Data | | D6 | GPIO43 | DC | Display Data/Command | | D7 | GPIO44 | CS | Display Chip Select |
Example
espp::Byte90 &byte90 = espp::Byte90::get(); byte90.set_log_level(espp::Logger::Verbosity::INFO); // initialize the accelerometer if (!byte90.initialize_accelerometer()) { logger.error("Failed to initialize accelerometer!"); } // initialize the LCD if (!byte90.initialize_lcd()) { logger.error("Failed to initialize LCD!"); return; } // set the pixel buffer to be 50 lines high static constexpr size_t pixel_buffer_size = byte90.lcd_width() * 50; // initialize the LVGL display for the Byte90 if (!byte90.initialize_display(pixel_buffer_size)) { logger.error("Failed to initialize display!"); return; } // create the GUI: builds the UI (label and circle layer) and starts the // task which updates LVGL. All of its public methods are thread-safe, so // the button callback and main loop below can call them directly. static Gui gui({.log_level = espp::Logger::Verbosity::INFO}); gui.set_label_text("Drawing circles\nto the screen."); // initialize the button; each press increments the display brightness by // 10% (wrapping back around after 100%) and cycles the display rotation logger.info("Initializing the button"); auto on_button_pressed = [&](const auto &event) { if (event.active) { // increment the brightness by 10%, looping back to 0% after 100% auto brightness = byte90.brightness(); brightness = std::fmod(brightness + 10.0f, 100.0f); logger.info("Setting brightness to {:.0f}%", brightness); byte90.brightness(brightness); // cycle the rotation of the display; the Gui resizes / re-aligns the // UI to match gui.next_rotation(); } }; byte90.initialize_button(on_button_pressed); // set the display brightness to be 75% byte90.brightness(75.0f); while (true) { auto start = esp_timer_get_time(); // if there are 10 circles on the screen, clear them if (gui.visible_circle_count() >= Gui::MAX_CIRCLES) { gui.clear_circles(); } else { // draw a circle of circles on the screen (just draw the next circle) int middle_x = byte90.rotated_display_width() / 2; int middle_y = byte90.rotated_display_height() / 2; static constexpr int radius = 30; float angle = gui.visible_circle_count() * 2.0f * std::numbers::pi_v<float> / Gui::MAX_CIRCLES; int x = middle_x + radius * std::cos(angle); int y = middle_y + radius * std::sin(angle); gui.draw_circle(x, y, 5); } auto end = esp_timer_get_time(); auto elapsed = end - start; std::this_thread::sleep_for(100ms - std::chrono::microseconds(elapsed)); }
Public Types
-
using button_callback_t = espp::Interrupt::event_callback_fn
Alias for the button callback function.
-
using AccelerometerData = Accelerometer::Data
Alias for the Accelerometer data type.
-
using accel_callback_t = std::function<void(const std::chrono::high_resolution_clock::time_point ×tamp, const std::vector<AccelerometerData> &data)>
Alias for an accelerometer interrupt callback.
Public Functions
-
inline I2c &internal_i2c()
Get a reference to the internal I2C bus
Note
The internal I2C bus is used for the accelerometer
- Returns:
A reference to the internal I2C bus
-
inline espp::Interrupt &interrupts()
Get a reference to the interrupts
- Returns:
A reference to the interrupts
-
bool initialize_button(const button_callback_t &callback = nullptr)
Initialize the button
- Parameters:
callback – The callback function to call when the button is pressed
- Returns:
true if the button was successfully initialized, false otherwise
-
bool button_state() const
Get the button state
- Returns:
The button state (true = button pressed, false = button released)
-
bool initialize_accelerometer(const accel_callback_t &callback = nullptr)
Initialize the accelerometer
Note
This will configure the accelerometer interrupt pin which will automatically call the accel callback function when the accel interrupt occurs
- Parameters:
callback – The callback function to call when the accelerometer interrupt occurs
- Returns:
true if the accelerometer was successfully initialized, false otherwise
-
inline std::shared_ptr<Accelerometer> accelerometer() const
Get the Accelerometer shared pointer
- Returns:
A shared pointer to the Accelerometer instance
-
inline std::vector<AccelerometerData> accelerometer_data()
Get the most recent accelerometer data
- Returns:
The most recent accelerometer data
-
bool initialize_lcd()
Initialize the LCD (low level display driver)
- Returns:
true if the LCD was successfully initialized, false otherwise
-
bool initialize_display(size_t pixel_buffer_size)
Initialize the display (lvgl display driver)
Note
This will also allocate two full frame buffers in the SPIRAM
- Parameters:
pixel_buffer_size – The size of the pixel buffer
- Returns:
true if the display was successfully initialized, false otherwise
-
size_t rotated_display_width() const
Get the display width in pixels, according to the current orientation
- Returns:
The display width in pixels, according to the current orientation
-
size_t rotated_display_height() const
Get the display height in pixels, according to the current orientation
- Returns:
The display height in pixels, according to the current orientation
-
std::shared_ptr<Display<Pixel>> display() const
Get a shared pointer to the display
- Returns:
A shared pointer to the display
-
inline const std::shared_ptr<DisplayDriver> &display_driver() const
Get a shared pointer to the low-level display driver
- Returns:
A shared pointer to the display driver
-
void brightness(float brightness)
Set the brightness of the backlight
- Parameters:
brightness – The brightness of the backlight as a percentage (0 - 100)
-
float brightness() const
Get the brightness of the backlight
- Returns:
The brightness of the backlight as a percentage (0 - 100)
-
Pixel *vram0() const
Get the VRAM 0 pointer (DMA memory used by LVGL)
Note
This is the memory used by LVGL for rendering
Note
This is null unless initialize_display() has been called
- Returns:
The VRAM 0 pointer
-
Pixel *vram1() const
Get the VRAM 1 pointer (DMA memory used by LVGL)
Note
This is the memory used by LVGL for rendering
Note
This is null unless initialize_display() has been called
- Returns:
The VRAM 1 pointer
-
uint8_t *frame_buffer0() const
Get the frame buffer 0 pointer
Note
This memory is designed to be used by the application developer and is provided as a convenience. It is not used by the display driver.
Note
This is null unless initialize_display() has been called
- Returns:
The frame buffer 0 pointer
-
uint8_t *frame_buffer1() const
Get the frame buffer 1 pointer
Note
This memory is designed to be used by the application developer and is provided as a convenience. It is not used by the display driver.
Note
This is null unless initialize_display() has been called
- Returns:
The frame buffer 1 pointer
-
void write_lcd_frame(const uint16_t x, const uint16_t y, const uint16_t width, const uint16_t height, uint8_t *data)
Write a frame to the LCD
Note
This method queues the data to be written to the LCD, only blocking if there is an ongoing SPI transaction
- Parameters:
x – The x coordinate
y – The y coordinate
width – The width of the frame, in pixels
height – The height of the frame, in pixels
data – The data to write
-
void write_lcd_lines(int xs, int ys, int xe, int ye, const uint8_t *data, uint32_t user_data)
Write lines to the LCD
Note
This method queues the panel transfer asynchronously and may return before the write has completed.
- Parameters:
xs – The x start coordinate
ys – The y start coordinate
xe – The x end coordinate
ye – The y end coordinate
data – The data to write
user_data – User data to pass to the SPI transaction callback
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns:
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters:
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns:
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters:
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters:
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns:
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters:
rate_limit – The rate limit to use for the logger
Public Static Functions
-
static inline Byte90 &get()
Access the singleton instance of the Byte90 class.
- Returns:
Reference to the singleton instance of the Byte90 class
-
static inline constexpr size_t lcd_width()
Get the width of the LCD in pixels
- Returns:
The width of the LCD in pixels
-
static inline constexpr size_t lcd_height()
Get the height of the LCD in pixels
- Returns:
The height of the LCD in pixels
-
static inline constexpr auto get_lcd_dc_gpio()
Get the GPIO pin for the LCD data/command signal
- Returns:
The GPIO pin for the LCD data/command signal
-
using button_callback_t = espp::Interrupt::event_callback_fn