Skip to content

Commit

Permalink
Merge branch 'master' into doxygen
Browse files Browse the repository at this point in the history
  • Loading branch information
meganetaaan committed Apr 14, 2024
2 parents 7678366 + 96fa787 commit 5a5f483
Show file tree
Hide file tree
Showing 18 changed files with 321 additions and 90 deletions.
51 changes: 51 additions & 0 deletions examples/PlatformIO_SDL/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[platformio]
default_envs = native

[env]
lib_extra_dirs=../../../
lib_deps = m5stack/M5Unified@^0.1.11

[env:native]
platform = native
build_type = debug
build_flags = -O0 -xc++ -std=c++14 -lSDL2
-I"/usr/local/include/SDL2" ; for intel mac homebrew SDL2
-L"/usr/local/lib" ; for intel mac homebrew SDL2
-I"${sysenv.HOMEBREW_PREFIX}/include/SDL2" ; for arm mac homebrew SDL2
-L"${sysenv.HOMEBREW_PREFIX}/lib" ; for arm mac homebrew SDL2

[env:native_m5stack]
extends = native
platform = native
build_flags = ${env:native.build_flags}
-DM5GFX_BOARD=board_M5Stack

[env:native_stickCPlus]
extends = native
platform = native
build_flags = ${env:native.build_flags}
-DM5GFX_SCALE=2
-DM5GFX_ROTATION=0
-DM5GFX_BOARD=board_M5StickCPlus

[esp32_base]
build_type = debug
platform = espressif32
board = esp32dev
upload_speed = 1500000
monitor_speed = 115200
monitor_filters = esp32_exception_decoder

[env:esp32_arduino]
extends = esp32_base
framework = arduino
28 changes: 28 additions & 0 deletions examples/PlatformIO_SDL/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <M5Unified.h>
#include <Avatar.h>

using namespace m5avatar;

Avatar avatar;

void setup()
{
M5.begin();
avatar.init(); // start drawing

// adjust position
const auto r = avatar.getFace()->getBoundingRect();
const auto scale_w = M5.Display.width() / (float)r->getWidth();
const auto scale_h = M5.Display.height() / (float)r->getHeight();
const auto scale = std::min(scale_w, scale_h);
avatar.setScale(scale);
const auto offs_x = (r->getWidth() - M5.Display.width()) / 2;
const auto offs_y = (r->getHeight() - M5.Display.height()) / 2;
avatar.setPosition(-offs_y, -offs_x);
}

void loop()
{
// avatar's face updates in another thread
// so no need to loop-by-loop rendering
}
25 changes: 25 additions & 0 deletions examples/PlatformIO_SDL/src/sdl_main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <M5GFX.h>
#if defined ( SDL_h_ )

void setup(void);
void loop(void);

__attribute__((weak))
int user_func(bool* running)
{
setup();
do
{
loop();
} while (*running);
return 0;
}

int main(int, char**)
{
// The second argument is effective for step execution with breakpoints.
// You can specify the time in milliseconds to perform slow execution that ensures screen updates.
return lgfx::Panel_sdl::main(user_func, 128);
}

#endif
14 changes: 9 additions & 5 deletions library.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
}
],
"license": "MIT",
"dependencies": {
},
"version": "0.8.4",
"frameworks": "arduino",
"platforms": "espressif32"
"dependencies": [
{
"name": "M5Unified",
"version": ">=0.1.11"
}
],
"version": "0.9.2",
"frameworks": ["arduino", "espidf", "*"],
"platforms": ["espressif32", "native"]
}
3 changes: 2 additions & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=M5Stack_Avatar
version=0.8.4
version=0.9.2
author=Shinya Ishikawa
maintainer=Shinya Ishikawa<[email protected]>
sentence=Yet another avatar module for M5Stack
Expand All @@ -8,3 +8,4 @@ category=Device Control
url=https://platformio.org/lib/show/4529/M5Stack-Avatar
architectures=esp32
includes=Avatar.h
depends=M5Unified
114 changes: 81 additions & 33 deletions src/Avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,54 @@
// license information.

#include "Avatar.h"

#ifndef PI
#define PI 3.1415926535897932384626433832795
#endif

namespace m5avatar {
const uint32_t DEFAULT_STACK_SIZE = 1024;

unsigned int seed = 0;

#ifndef rand_r
#define init_rand() srand(seed)
#define _rand() rand()
#else
#define init_rand() ;
#define _rand() rand_r(&seed)
#endif

#ifdef SDL_h_
#define TaskResult() return 0
#define TaskDelay(ms) lgfx::delay(ms)
long random(long howbig) {
return std::rand() % howbig;
}
#else
#define TaskResult() vTaskDelete(NULL)
#define TaskDelay(ms) vTaskDelay(ms/portTICK_PERIOD_MS)
#endif

// TODO(meganetaaan): make read-only
DriveContext::DriveContext(Avatar *avatar) : avatar{avatar} {}

Avatar *DriveContext::getAvatar() { return avatar; }

TaskHandle_t drawTaskHandle;

void drawLoop(void *args) {
TaskResult_t drawLoop(void *args) {
DriveContext *ctx = reinterpret_cast<DriveContext *>(args);
Avatar *avatar = ctx->getAvatar();
while (avatar->isDrawing()) {
if (avatar->isDrawing()) {
avatar->draw();
}
vTaskDelay(33);
TaskDelay(10);
}
vTaskDelete(NULL);
TaskResult();
}

void facialLoop(void *args) {
TaskResult_t facialLoop(void *args) {
int c = 0;
DriveContext *ctx = reinterpret_cast<DriveContext *>(args);
Avatar *avatar = ctx->getAvatar();
Expand All @@ -36,17 +59,21 @@ void facialLoop(void *args) {
unsigned long last_saccade_millis = 0;
unsigned long last_blink_millis = 0;
bool eye_open = true;
float vertical = 0.0f;
float horizontal = 0.0f;
float breath = 0.0f;
init_rand();
while (avatar->isDrawing()) {

if ((millis() - last_saccade_millis) > saccade_interval) {
float vertical = rand_r(&seed) / (RAND_MAX / 2.0) - 1;
float horizontal = rand_r(&seed) / (RAND_MAX / 2.0) - 1;
if ((lgfx::millis() - last_saccade_millis) > saccade_interval) {
vertical = _rand() / (RAND_MAX / 2.0) - 1;
horizontal = _rand() / (RAND_MAX / 2.0) - 1;
avatar->setGaze(vertical, horizontal);
saccade_interval = 500 + 100 * random(20);
last_saccade_millis = millis();
last_saccade_millis = lgfx::millis();
}

if ((millis()- last_blink_millis) > blink_interval) {
if ((lgfx::millis()- last_blink_millis) > blink_interval) {
if (eye_open) {
avatar->setEyeOpenRatio(1);
blink_interval = 2500 + 100 * random(20);
Expand All @@ -55,14 +82,14 @@ void facialLoop(void *args) {
blink_interval = 300 + 10 * random(20);
}
eye_open = !eye_open;
last_blink_millis = millis();
last_blink_millis = lgfx::millis();
}
c = (c + 1) % 100;
float f = sin(c * 2 * PI / 100.0);
avatar->setBreath(f);
vTaskDelay(33);
breath = sin(c * 2 * PI / 100.0);
avatar->setBreath(breath);
TaskDelay(33);
}
vTaskDelete(NULL);
TaskResult();
}

Avatar::Avatar() : Avatar(new Face()) {}
Expand All @@ -83,27 +110,37 @@ Avatar::Avatar(Face *face)
colorDepth{1},
batteryIconStatus{BatteryIconStatus::invisible}{}

Avatar::~Avatar() {
delete face;
}

void Avatar::setFace(Face *face) { this->face = face; }

Face *Avatar::getFace() const { return face; }

void Avatar::addTask(TaskFunction_t f, const char* name) {
void Avatar::addTask(TaskFunction_t f
, const char* name
, const uint32_t stack_size
, UBaseType_t priority
, TaskHandle_t* const task_handle
, const BaseType_t core_id) {
DriveContext *ctx = new DriveContext(this);
#ifdef SDL_h_
if (task_handle == NULL) {
SDL_CreateThreadWithStackSize(f, name, stack_size, ctx);
} else {
*task_handle = SDL_CreateThreadWithStackSize(f, name, stack_size, ctx);
}
#else
// TODO(meganetaaan): set a task handler
xTaskCreateUniversal(f, /* Function to implement the task */
name, /* Name of the task */
DEFAULT_STACK_SIZE, /* Stack size in words */
ctx, /* Task input parameter */
4, /* P2014riority of the task */
NULL, /* Task handle. */
APP_CPU_NUM);
// xTaskCreatePinnedToCore(f, /* Function to implement the task */
// name, /* Name of the task */
// DEFAULT_STACK_SIZE, /* Stack size in words */
// ctx, /* Task input parameter */
// 1, /* P2014riority of the task */
// NULL, /* Task handle. */
// 1); /* Core where the task should run */
xTaskCreateUniversal(f, /* Function to implement the task */
name, /* Name of the task */
stack_size, /* Stack size in words */
ctx, /* Task input parameter */
priority, /* Priority of the task */
task_handle, /* Task handle. */
core_id); /* Core No*/
#endif
}

void Avatar::init(int colorDepth) {
Expand All @@ -114,11 +151,15 @@ void Avatar::init(int colorDepth) {
void Avatar::stop() { _isDrawing = false; }

void Avatar::suspend() {
#ifndef SDL_h_
vTaskSuspend(drawTaskHandle);
#endif
}

void Avatar::resume() {
#ifndef SDL_h_
vTaskResume(drawTaskHandle);
#endif
}

void Avatar::start(int colorDepth) {
Expand All @@ -128,22 +169,27 @@ void Avatar::start(int colorDepth) {

this->colorDepth = colorDepth;
DriveContext *ctx = new DriveContext(this);
#ifdef SDL_h_
drawTaskHandle = SDL_CreateThreadWithStackSize(drawLoop, "drawLoop", 2048, ctx);
SDL_CreateThreadWithStackSize(facialLoop, "facialLoop", 1024, ctx);
#else
// TODO(meganetaaan): keep handle of these tasks
xTaskCreateUniversal(drawLoop, /* Function to implement the task */
"drawLoop", /* Name of the task */
2048, /* Stack size in words */
ctx, /* Task input parameter */
2, /* Priority of the task */
1, /* Priority of the task */
&drawTaskHandle, /* Task handle. */
APP_CPU_NUM);

xTaskCreateUniversal(facialLoop, /* Function to implement the task */
"facialLoop", /* Name of the task */
1024, /* Stack size in words */
ctx, /* Task input parameter */
3, /* Priority of the task */
2, /* Priority of the task */
NULL, /* Task handle. */
APP_CPU_NUM);
#endif
}

void Avatar::draw() {
Expand All @@ -159,7 +205,9 @@ void Avatar::draw() {
bool Avatar::isDrawing() { return _isDrawing; }

void Avatar::setExpression(Expression expression) {
suspend();
this->expression = expression;
resume();
}

Expression Avatar::getExpression() {
Expand Down Expand Up @@ -199,7 +247,7 @@ void Avatar::getGaze(float *vertical, float *horizontal) {
}

void Avatar::setSpeechText(const char *speechText) {
this->speechText = speechText;
this->speechText = String(speechText);
}

void Avatar::setSpeechFont(const lgfx::IFont *speechFont) {
Expand Down
Loading

0 comments on commit 5a5f483

Please sign in to comment.