Skip to content
Merged
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
44 changes: 35 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
strategy:
matrix:
env: [esp32, matrixportal]

steps:
- name: Checkout
Expand All @@ -23,7 +24,7 @@ jobs:
- name: Cache
uses: actions/cache@v4
with:
key: cache-${{ github.ref_name }}
key: cache-${{ matrix.env }}-${{ github.ref_name }}
path: |
~/.cache/pip
~/.platformio/.cache
Expand All @@ -50,20 +51,45 @@ jobs:
cache-dependency-path: 'web/pnpm-lock.yaml'

- name: Install C++ dependencies
run: pio pkg install
run: pio pkg install --environment ${{ matrix.env }}

- name: Build firmware
run: pio run --environment stable
run: pio run --environment ${{ matrix.env }}

- name: Build filesystem
run: pio run --target buildfs --environment stable
run: pio run --target buildfs --environment ${{ matrix.env }}

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.env }}
path: .pio/build/${{ matrix.env }}/

release:
needs: build
runs-on: ubuntu-latest
if: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }}
permissions:
contents: write

steps:
- name: Download build artifacts
uses: actions/download-artifact@v4

- name: Rename artifacts for release
run: |
mv build-esp32/firmware.bin build-esp32/esp32-firmware.bin
mv build-esp32/littlefs.bin build-esp32/esp32-littlefs.bin
mv build-matrixportal/firmware.bin build-matrixportal/matrixportal-firmware.bin
mv build-matrixportal/littlefs.bin build-matrixportal/matrixportal-littlefs.bin

- name: Release
if: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }}
uses: softprops/action-gh-release@v2
with:
make_latest: true
generate_release_notes: true
files: |
.pio/build/stable/firmware.bin
.pio/build/stable/littlefs.bin
build-esp32/esp32-firmware.bin
build-esp32/esp32-littlefs.bin
build-matrixportal/matrixportal-firmware.bin
build-matrixportal/matrixportal-littlefs.bin
7 changes: 7 additions & 0 deletions partitions-8mb.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x200000,
app1, app, ota_1, 0x210000,0x200000,
spiffs, data, spiffs, 0x410000,0x3E0000,
coredump, data, coredump,0x7F0000,0x10000,
30 changes: 25 additions & 5 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:stable]
platform = espressif32
board = esp32dev
; Shared settings
[env]
framework = arduino
platform = platformio/espressif32@6.12.0
monitor_speed = 115200
board_build.filesystem = littlefs
board_build.partitions = partitions.csv
Expand All @@ -38,8 +38,6 @@ lib_deps =
https://github.com/bitbank2/AnimatedGIF.git#2.2.0
; Decode JPEGs
https://github.com/bitbank2/JPEGDEC.git#1.8.3
; MPU6050 gyro/accelerometer
jrowberg/I2Cdevlib-MPU6050
build_flags =
; esp32-idf library debug level
; -DCORE_DEBUG_LEVEL=3
Expand All @@ -49,3 +47,25 @@ build_flags =
; -DUSE_GFX_LITE=1
; build without AdafruitGFX; no drawing, text or fonts!
; -DNO_GFX=1

; Reference ESP32 devkit board
[env:esp32]
board = esp32dev
lib_deps =
${env.lib_deps}
; MPU6050 gyro/accelerometer
jrowberg/I2Cdevlib-MPU6050

; Adafruit MatrixPortal S3
[env:matrixportal]
board = adafruit_matrixportal_esp32s3
board_build.partitions = partitions-8mb.csv
board_build.arduino.memory_type = qio_qspi
; Disable flashing the TinyUF2 bootloader image
board_upload.arduino.flash_extra_images =
lib_deps =
${env.lib_deps}
; on-board LIS3DH accelerometer
adafruit/Adafruit LIS3DH @ 1.3.0
; on-board NeoPixel
adafruit/Adafruit NeoPixel @ ^1.12.0
72 changes: 66 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "main.h"
#include "modules/monitor.h"

HUB75_I2S_CFG::i2s_pins pins = {R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
HUB75_I2S_CFG ledConfig(
Expand All @@ -11,7 +10,7 @@ HUB75_I2S_CFG ledConfig(
false, // DMA double buffer (double RAM)
I2C_CLK, // i2s clock speed
LAT_BLANKING, // how many clock cycles to blank before/after LAT change
true, // i2s clock phase (positive/negative edge)
CLK_PHASE, // i2s clock phase (positive/negative edge)
60, // minimum refresh rate
PIXEL_COLOR_DEPTH_BITS // color depth
);
Expand All @@ -30,6 +29,11 @@ ModeSelector selector;
Config conf(updateConfig);
Renderer *currentMode = nullptr;
Monitor* monitor = nullptr;
StatusLed statusLed;
wl_status_t prevWifiStatus = WL_IDLE_STATUS;
wifi_mode_t prevWifiMode = WIFI_MODE_NULL;
bool otaWasUpdating = false;
ulong lastModePoll = 0;

void updateQrText() {
const char* url = wifi.getUrl();
Expand Down Expand Up @@ -87,6 +91,7 @@ bool changeMode(draw_mode newMode) {
updateQrText();
}

statusLed.onModeChanged(newMode);
return true;
};

Expand Down Expand Up @@ -114,14 +119,19 @@ void updateConfig(JsonDocument& newConfig) {
if (monitor != nullptr) {
monitor->setEnabled(newConfig["monitor"]["enable"].as<bool>());
}

statusLed.setEnabled(newConfig["statusled"]["enable"].as<bool>());
};

void setup() {
Log::instance()->begin(115200);
statusLed.init();
statusLed.onBoot();

// Initialize LittleFS
if (!LittleFS.begin()) {
Log::instance()->error("LittleFS error\n");
statusLed.onFatalError();

return;
}
Expand All @@ -131,28 +141,45 @@ void setup() {

// Configure logs
Log::instance()->setLevel(conf.current["log"]["level"].as<log_level>());
statusLed.setEnabled((conf.current["statusled"]["enable"] | 1) != 0);

// Initialize LED matrix
display = setupLED(ledConfig);
if (display == nullptr) {
Log::instance()->error("Error setting up LED matrix\n");
statusLed.onFatalError();

return;
}
display->setBrightness(conf.current["panel"]["brightness"].as<uint8_t>());

// Initialize gyroscope
// Initialize orientation sensor
if (!selector.init()) {
return;
Log::instance()->error("Mode selector unavailable, staying in default mode\n");
}

// Start media as default mode
currentMode = &media;
currentMode->open();
drawMode = DRAW_MODE_IMAGE;

// Initialize WiFi
String ssid = conf.current["wifi"]["ssid"].as<String>();
String password = conf.current["wifi"]["password"].as<String>();
if (!wifi.connect(ssid.c_str(), password.c_str())) {
statusLed.onFatalError();

return;
}

if (wifi.getMode() & WIFI_MODE_AP) {
statusLed.onApStarted();
} else {
statusLed.onWifiConnected();
prevWifiStatus = WL_CONNECTED;
}
prevWifiMode = wifi.getMode();

updateQrText();

// Initialize log WebSocket
Expand Down Expand Up @@ -183,6 +210,11 @@ void setup() {
status["heap"]["minFree"] = ESP.getMinFreeHeap();
status["heap"]["maxFreeBlock"] = ESP.getMaxAllocHeap();
status["flash"] = ESP.getFlashChipSize();
status["psram"]["found"] = psramFound();
status["psram"]["size"] = ESP.getPsramSize();
status["psram"]["free"] = ESP.getFreePsram();
status["psram"]["minFree"] = ESP.getMinFreePsram();
status["psram"]["maxFreeBlock"] = ESP.getMaxAllocPsram();
status["firmware"]["size"] = ESP.getFreeSketchSpace(); // see: https://github.com/espressif/arduino-esp32/issues/3131
status["firmware"]["used"] = ESP.getSketchSize();
status["firmware"]["version"] = VERSION; // defined at build time, see pre_version.py
Expand All @@ -205,17 +237,45 @@ void setup() {
setupOk = true;
};

ulong lastModePoll = 0;

void loop() {
if (!setupOk) {
return;
}

ota.loop();
statusLed.tick();

bool nowUpdating = ota.isUpdating();
if (nowUpdating && !otaWasUpdating) {
statusLed.onOtaStart();
} else if (!nowUpdating && otaWasUpdating) {
statusLed.onOtaEnd();
}
otaWasUpdating = nowUpdating;

if (millis() - lastModePoll >= 1000) {
lastModePoll = millis();

wifi_mode_t wifiMode = wifi.getMode();
if (wifiMode != prevWifiMode) {
if (wifiMode & WIFI_MODE_AP) {
statusLed.onApStarted();
}
if (!(wifiMode & WIFI_MODE_STA)) {
prevWifiStatus = WL_IDLE_STATUS;
}
prevWifiMode = wifiMode;
}
if (wifiMode & WIFI_MODE_STA) {
wl_status_t wifiStatus = WiFi.status();
if (wifiStatus != WL_CONNECTED && prevWifiStatus == WL_CONNECTED) {
statusLed.onWifiReconnecting();
} else if (wifiStatus == WL_CONNECTED && prevWifiStatus != WL_CONNECTED) {
statusLed.onWifiConnected();
}
prevWifiStatus = wifiStatus;
}

if (changeMode(selector.getMode())) {
return;
}
Expand Down
36 changes: 31 additions & 5 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "modules/config.h"
#include "modules/wifi.h"
#include "modules/led.h"
#include "modules/monitor.h"
#include "modules/statusled.h"
#include "modules/modeselector.h"
#include "modes/media.h"
#include "modes/map.h"
Expand All @@ -14,30 +16,54 @@
#include "modules/ota.h"
#include <ArduinoJson.h>

// Pins
#if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3)
// Pins for the Adafruit MatrixPortal S3 board
#define R1_PIN 42
#define G1_PIN 41
#define B1_PIN 40
#define R2_PIN 38
#define G2_PIN 39
#define B2_PIN 37
#define A_PIN 45
#define B_PIN 36
#define C_PIN 48
#define D_PIN 35
#define E_PIN 21
#define LAT_PIN 47
#define OE_PIN 14
#define CLK_PIN 2
#else
// Pins for the esp32 board
#define R1_PIN R1_PIN_DEFAULT
#define G1_PIN G1_PIN_DEFAULT
#define B1_PIN B1_PIN_DEFAULT
#define R2_PIN R2_PIN_DEFAULT
#define G2_PIN G2_PIN_DEFAULT
#define B2_PIN B2_PIN_DEFAULT
#define A_PIN A_PIN_DEFAULT
#define B_PIN 22 // changed, was 19
#define B_PIN 22
#define C_PIN C_PIN_DEFAULT
#define D_PIN D_PIN_DEFAULT
#define E_PIN 32 // changed, was -1
#define E_PIN 32
#define LAT_PIN LAT_PIN_DEFAULT
#define OE_PIN OE_PIN_DEFAULT
#define CLK_PIN CLK_PIN_DEFAULT
#endif

// Matrix
#define WIDTH MATRIX_WIDTH
#define HEIGHT 64 // changed, was 32
#define HEIGHT 64
#define CHAIN CHAIN_LENGTH
#define ROWS_IN_PARALLEL MATRIX_ROWS_IN_PARALLEL
#define PIXEL_COLOR_DEPTH_BITS 8
#define LAT_BLANKING 2
#define I2C_CLK HUB75_I2S_CFG::HZ_8M
#define I2C_CLK HUB75_I2S_CFG::HZ_20M

#if defined(ARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3)
#define CLK_PHASE false
#else
#define CLK_PHASE true
#endif

// Config
#define FPS 15
Expand Down
Loading
Loading