Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/ArduinoLogo/ArduinoLogo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
INCBIN(test, "/home/user/Downloads/test.bin");
*/

// Default: video over the USB-C port
Arduino_Video Display;
// To drive the Giga Display Shield on a Portenta H7 + Portenta Mid Carrier, use:
// Arduino_Video Display(800, 480, GigaDisplayShield);

Image img_arduinologo(ENCODING_RGB16, (uint8_t *) texture_raw, 300, 300);

Expand Down
27 changes: 15 additions & 12 deletions src/Arduino_Video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@

#include "Arduino_Video.h"

#include "video_backend.h"
#include "dsi.h"
#include "logging.h"
extern "C" {
#include "video_modes.h"
}

#if defined(__ZEPHYR__) && defined(ARDUINO_GIGA)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/display.h>
Expand All @@ -43,7 +44,7 @@ void lvgl_displayFlushing(lv_display_t *display, const lv_area_t *area, unsigned
#endif
#endif /* __has_include ("lvgl.h") */

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
/* Note: These variables are defined in the global scope because the LVGL
* 'lvgl_displayFlushing' callback is a static function */
const struct device *display_dev;
Expand Down Expand Up @@ -96,7 +97,7 @@ int Arduino_Video::begin() {
textFont(Font_5x7);
#endif

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__) // Backend for Arduino Giga R1
#if defined(ARDUINO_VIDEO_DIRECT_FB) // Framebuffer-managed panel (ST7701)
display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));

if (!device_is_ready(display_dev)) {
Expand All @@ -107,6 +108,8 @@ int Arduino_Video::begin() {
}

#if DT_NODE_EXISTS(DT_NODELABEL(st7701))
/* The ST7701 panel is deferred-init: bring it up now that the DSI host and
LTDC are ready (its boot-time init runs too early and fails). */
const struct device *panel_dev = DEVICE_DT_GET(DT_NODELABEL(st7701));
if (!device_is_ready(panel_dev)) {
if (zephyr::arduino::init_dev_apply_pinctrl(panel_dev) < 0) {
Expand Down Expand Up @@ -207,7 +210,7 @@ void Arduino_Video::end() {
void Arduino_Video::beginDraw() {
ArduinoGraphics::beginDraw();

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
uint16_t *fb = (uint16_t *)display_get_framebuffer(display_dev);
memset(fb, 0, display_caps.x_resolution * display_caps.y_resolution * sizeof(uint16_t));
#else
Expand All @@ -218,7 +221,7 @@ void Arduino_Video::beginDraw() {
void Arduino_Video::endDraw() {
ArduinoGraphics::endDraw();

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
// no need to explicitly flush, as we are writing directly to the framebuffer
#else
dsi_drawCurrentFrameBuffer();
Expand All @@ -229,7 +232,7 @@ void Arduino_Video::clear() {
[[maybe_unused]] uint32_t bg = ArduinoGraphics::background();
[[maybe_unused]] uint32_t x_size, y_size;

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
uint16_t *fb = (uint16_t *)display_get_framebuffer(display_dev);
memset(fb, 0, display_caps.x_resolution * display_caps.y_resolution * 2);
#else
Expand Down Expand Up @@ -262,15 +265,15 @@ void Arduino_Video::set(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
return;
}

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
if (x_rot >= display_caps.x_resolution || y_rot >= display_caps.y_resolution)
return;
#else
if (x_rot >= dsi_getDisplayXSize() || y_rot >= dsi_getDisplayYSize())
return;
#endif

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
// The pixel is written directly into the framebuffer in RGB565 format.
// Rotation is automatically handled if the display is rotated.
uint16_t color = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
Expand Down Expand Up @@ -318,7 +321,7 @@ void lvgl_displayFlushing(lv_display_t *disp, const lv_area_t *area, unsigned ch
h = temp;
}

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
uint16_t *dst = buffer;
uint16_t *src = (uint16_t *)px_map;

Expand All @@ -336,7 +339,7 @@ void lvgl_displayFlushing(lv_display_t *disp, const lv_area_t *area, unsigned ch
#endif //end lvgl

int Arduino_Video::drawBuffer([[maybe_unused]]uint16_t x, [[maybe_unused]]uint16_t y, [[maybe_unused]]const void *buf) {
#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
if (!device_is_ready(display_dev)) {
return -ENODEV;
}
Expand All @@ -347,7 +350,7 @@ int Arduino_Video::drawBuffer([[maybe_unused]]uint16_t x, [[maybe_unused]]uint16
}

void *Arduino_Video::getFramebuffer() {
#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
/* * In Zephyr, 'buffer' is the pointer allocated or retrieved from the display device during begin() */
void *fb = display_get_framebuffer(display_dev);
return fb;
Expand All @@ -356,7 +359,7 @@ void *Arduino_Video::getFramebuffer() {
#endif
}

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
void Arduino_Video::setFrameDesc(uint16_t w, uint16_t h, uint16_t pitch, uint32_t buf_size) {
desc.buf_size = buf_size;
desc.width = w; /** Number of pixels between consecutive rows in the data buffer */
Expand Down
33 changes: 31 additions & 2 deletions src/DisplayShield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@

#include "Arduino.h"
#include "anx7625.h"
#include "video_backend.h"
extern "C" {
#include "video_modes.h"
}

#if defined(ARDUINO_GIGA) && defined(__ZEPHYR__)
#if defined(ARDUINO_VIDEO_DIRECT_FB)
// Panel driven by the Zephyr ST7701 driver; the library uses the framebuffer.
int GigaDisplayShieldClass::init([[maybe_unused]]int edidmode) {
return 0;
}
Expand All @@ -31,9 +33,31 @@ int GigaDisplayShieldClass::getStatus() {
}

GigaDisplayShieldClass GigaDisplayShield;
#endif /* ARDUINO_GIGA && __ZEPHYR__ */
#elif defined(ARDUINO_PORTENTA_H7_M7) && defined(__ZEPHYR__)
// The Giga Display Shield needs the core built with the Portenta H7 Giga
// Display configuration (ST7701 panel enabled in devicetree).
int GigaDisplayShieldClass::init([[maybe_unused]]int edidmode) {
return -1;
}

int GigaDisplayShieldClass::getEdidMode([[maybe_unused]]int h, [[maybe_unused]] int v) {
return EDID_MODE_480x800_60Hz;
}

int GigaDisplayShieldClass::getStatus() {
return 0;
}

GigaDisplayShieldClass GigaDisplayShield;
#endif

int USBCVideoClass::init(int edidmode) {
#if defined(ARDUINO_VIDEO_DIRECT_FB)
/* USB-C/ANX7625 pipeline is not built in a framebuffer-managed (ST7701)
configuration; the panel is driven directly by its Zephyr driver. */
(void)edidmode;
return -1;
#else
struct edid recognized_edid;
int err_code = 0;

Expand Down Expand Up @@ -61,6 +85,7 @@ int USBCVideoClass::init(int edidmode) {
}

return 0;
#endif
}

int USBCVideoClass::getEdidMode(int h, int v) {
Expand All @@ -70,9 +95,13 @@ int USBCVideoClass::getEdidMode(int h, int v) {
}

int USBCVideoClass::getStatus() {
#if defined(ARDUINO_VIDEO_DIRECT_FB)
return 0;
#else
int detected = anx7625_get_hpd_event(0);

return detected;
#endif
}

USBCVideoClass USBCVideo;
3 changes: 2 additions & 1 deletion src/anx7625.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
#include <Arduino.h>

#include "logging.h"
#include "video_backend.h"

#if defined(ARDUINO_PORTENTA_H7_M7)
#if defined(ARDUINO_PORTENTA_H7_M7) && !defined(ARDUINO_VIDEO_DIRECT_FB)

#include "dsi.h"
#include "anx7625.h"
Expand Down
4 changes: 3 additions & 1 deletion src/dsi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

*/

#if defined(__ZEPHYR__) && !defined(ARDUINO_GIGA)
#include "video_backend.h"

#if defined(__ZEPHYR__) && !defined(ARDUINO_VIDEO_DIRECT_FB)

#include <Arduino.h>
#include <zephyr/kernel.h>
Expand Down
3 changes: 2 additions & 1 deletion src/platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@

#include "platform.h"
#include "logging.h"
#include "video_backend.h"

#if __has_include("lvgl.h")
#include "lvgl.h"
#endif

#if defined(ARDUINO_PORTENTA_H7_M7)
#if defined(ARDUINO_PORTENTA_H7_M7) && !defined(ARDUINO_VIDEO_DIRECT_FB)

/* GPIO specifications from devicetree */
#define ANX7625_NODE DT_NODELABEL(anx7625)
Expand Down
34 changes: 34 additions & 0 deletions src/video_backend.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
This file is part of the Arduino_Video library.

Copyright (C) Arduino s.r.l. and/or its affiliated companies

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

*/

#ifndef _ARDUINO_VIDEO_BACKEND_H
#define _ARDUINO_VIDEO_BACKEND_H

/*
* ARDUINO_VIDEO_DIRECT_FB selects the display backend at build time:
*
* - defined -> the panel is fully managed by a Zephyr display driver
* (ST7701 on the Giga Display Shield, either on the Giga R1 or
* on a Portenta H7 + midcarrier built with the Giga Display
* core configuration). The library draws straight into the
* LTDC framebuffer; the Zephyr driver performs the DSI panel
* bring-up at boot.
* - undefined -> the library drives the MIPI-DSI bridge itself (anx7625 over
* USB-C on the Portenta H7).
*/
#if defined(__ZEPHYR__)
#include <zephyr/devicetree.h>
#if DT_HAS_COMPAT_STATUS_OKAY(sitronix_st7701)
#define ARDUINO_VIDEO_DIRECT_FB 1
#endif
#endif

#endif /* _ARDUINO_VIDEO_BACKEND_H */
Loading