first commit
This commit is contained in:
commit
5893b00dd2
1669 changed files with 1982740 additions and 0 deletions
|
|
@ -0,0 +1,88 @@
|
|||
#include <M5Unified.h>
|
||||
|
||||
static bool got_notif_flag = false;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
M5.begin();
|
||||
M5.Power.Axp2101.disableIRQ(AXP2101_IRQ_ALL);
|
||||
M5.Power.Axp2101.clearIRQStatuses();
|
||||
M5.Power.Axp2101.enableIRQ(
|
||||
AXP2101_IRQ_BAT_CHG_UNDER_TEMP | AXP2101_IRQ_BAT_CHG_OVER_TEMP | // Battery temp in charging
|
||||
AXP2101_IRQ_VBUS_INSERT | AXP2101_IRQ_VBUS_REMOVE // Usb insert/remove
|
||||
);
|
||||
|
||||
M5.Display.setTextSize(3);
|
||||
}
|
||||
|
||||
void check_irq_statuses()
|
||||
{
|
||||
M5.Power.Axp2101.getIRQStatuses();
|
||||
|
||||
if(M5.Power.Axp2101.isBatChargerUnderTemperatureIrq())
|
||||
{
|
||||
M5.Display.drawString("BatUnderTempCharge", 50, 120);
|
||||
got_notif_flag = true;
|
||||
}
|
||||
if(M5.Power.Axp2101.isBatChargerOverTemperatureIrq())
|
||||
{
|
||||
M5.Display.drawString("BatOverTempCharge", 50, 120);
|
||||
got_notif_flag = true;
|
||||
}
|
||||
if(M5.Power.Axp2101.isVbusInsertIrq())
|
||||
{
|
||||
M5.Display.drawString("Usb inserted", 50, 120);
|
||||
got_notif_flag = true;
|
||||
}
|
||||
if(M5.Power.Axp2101.isVbusRemoveIrq())
|
||||
{
|
||||
M5.Display.drawString("Usb removed", 50, 120);
|
||||
got_notif_flag = true;
|
||||
}
|
||||
|
||||
M5.Power.Axp2101.clearIRQStatuses();
|
||||
}
|
||||
|
||||
void refresh_display()
|
||||
{
|
||||
static unsigned long started_time = 0;
|
||||
if(got_notif_flag == false) { return; }
|
||||
|
||||
unsigned long now_time = millis();
|
||||
if(started_time == 0)
|
||||
{
|
||||
started_time = now_time;
|
||||
}
|
||||
else if(now_time - started_time > 500)
|
||||
{
|
||||
started_time = 0;
|
||||
M5.Display.fillScreen(BLACK);
|
||||
got_notif_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.update();
|
||||
check_irq_statuses();
|
||||
refresh_display();
|
||||
vTaskDelay(50);
|
||||
}
|
||||
|
||||
#if !defined ( ARDUINO )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
124
libraries/M5Unified/examples/Basic/Button/Button.ino
Normal file
124
libraries/M5Unified/examples/Basic/Button/Button.ino
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
#include <M5Unified.h>
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
/// For models with EPD : refresh control
|
||||
M5.Display.setEpdMode(epd_mode_t::epd_fastest); // fastest but very-low quality.
|
||||
|
||||
if (M5.Display.width() < M5.Display.height())
|
||||
{ /// Landscape mode.
|
||||
M5.Display.setRotation(M5.Display.getRotation() ^ 1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.delay(1);
|
||||
|
||||
M5.update();
|
||||
//------------------- Button test
|
||||
/*
|
||||
/// List of available buttons:
|
||||
M5Stack BASIC/GRAY/GO/FIRE: BtnA,BtnB,BtnC
|
||||
M5Stack Core2: BtnA,BtnB,BtnC,BtnPWR
|
||||
M5Stick C/CPlus: BtnA,BtnB, BtnPWR
|
||||
M5Stick CoreInk: BtnA,BtnB,BtnC,BtnPWR,BtnEXT
|
||||
M5Paper: BtnA,BtnB,BtnC
|
||||
M5Station: BtnA,BtnB,BtnC,BtnPWR
|
||||
M5Tough: BtnPWR
|
||||
M5Atom M5AtomU: BtnA
|
||||
M5Stamp Pico/C3/C3U: BtnA
|
||||
*/
|
||||
|
||||
static constexpr const int colors[] = { TFT_WHITE, TFT_CYAN, TFT_RED, TFT_YELLOW, TFT_BLUE, TFT_GREEN };
|
||||
static constexpr const char* const names[] = { "none", "wasHold", "wasClicked", "wasPressed", "wasReleased", "wasDeciedCount" };
|
||||
|
||||
int w = M5.Display.width() / 5;
|
||||
int h = M5.Display.height();
|
||||
M5.Display.startWrite();
|
||||
|
||||
/// BtnPWR: "wasClicked"/"wasHold" can be use.
|
||||
/// BtnPWR of CoreInk: "isPressed"/"wasPressed"/"isReleased"/"wasReleased"/"wasClicked"/"wasHold"/"isHolding" can be use.
|
||||
int state = M5.BtnPWR.wasHold() ? 1
|
||||
: M5.BtnPWR.wasClicked() ? 2
|
||||
: M5.BtnPWR.wasPressed() ? 3
|
||||
: M5.BtnPWR.wasReleased() ? 4
|
||||
: M5.BtnPWR.wasDecideClickCount() ? 5
|
||||
: 0;
|
||||
|
||||
if (state)
|
||||
{
|
||||
M5_LOGI("BtnPWR:%s count:%d", names[state], M5.BtnPWR.getClickCount());
|
||||
M5.Display.fillRect(w*0, 0, w-1, h, colors[state]);
|
||||
}
|
||||
|
||||
/// BtnA,BtnB,BtnC,BtnEXT: "isPressed"/"wasPressed"/"isReleased"/"wasReleased"/"wasClicked"/"wasHold"/"isHolding" can be use.
|
||||
state = M5.BtnA.wasHold() ? 1
|
||||
: M5.BtnA.wasClicked() ? 2
|
||||
: M5.BtnA.wasPressed() ? 3
|
||||
: M5.BtnA.wasReleased() ? 4
|
||||
: M5.BtnA.wasDecideClickCount() ? 5
|
||||
: 0;
|
||||
if (state)
|
||||
{
|
||||
M5_LOGI("BtnA:%s count:%d", names[state], M5.BtnA.getClickCount());
|
||||
M5.Display.fillRect(w*1, 0, w-1, h, colors[state]);
|
||||
}
|
||||
|
||||
state = M5.BtnB.wasHold() ? 1
|
||||
: M5.BtnB.wasClicked() ? 2
|
||||
: M5.BtnB.wasPressed() ? 3
|
||||
: M5.BtnB.wasReleased() ? 4
|
||||
: M5.BtnB.wasDecideClickCount() ? 5
|
||||
: 0;
|
||||
if (state)
|
||||
{
|
||||
M5_LOGI("BtnB:%s count:%d", names[state], M5.BtnB.getClickCount());
|
||||
M5.Display.fillRect(w*2, 0, w-1, h, colors[state]);
|
||||
}
|
||||
|
||||
state = M5.BtnC.wasHold() ? 1
|
||||
: M5.BtnC.wasClicked() ? 2
|
||||
: M5.BtnC.wasPressed() ? 3
|
||||
: M5.BtnC.wasReleased() ? 4
|
||||
: M5.BtnC.wasDecideClickCount() ? 5
|
||||
: 0;
|
||||
if (state)
|
||||
{
|
||||
M5_LOGI("BtnC:%s count:%d", names[state], M5.BtnC.getClickCount());
|
||||
M5.Display.fillRect(w*3, 0, w-1, h, colors[state]);
|
||||
}
|
||||
|
||||
state = M5.BtnEXT.wasHold() ? 1
|
||||
: M5.BtnEXT.wasClicked() ? 2
|
||||
: M5.BtnEXT.wasPressed() ? 3
|
||||
: M5.BtnEXT.wasReleased() ? 4
|
||||
: M5.BtnEXT.wasDecideClickCount() ? 5
|
||||
: 0;
|
||||
if (state)
|
||||
{
|
||||
M5_LOGI("BtnEXT:%s count:%d", names[state], M5.BtnEXT.getClickCount());
|
||||
M5.Display.fillRect(w*4, 0, w-1, h, colors[state]);
|
||||
}
|
||||
M5.Display.endWrite();
|
||||
}
|
||||
|
||||
#if !defined ( ARDUINO ) && defined ( ESP_PLATFORM )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
291
libraries/M5Unified/examples/Basic/Displays/Displays.ino
Normal file
291
libraries/M5Unified/examples/Basic/Displays/Displays.ino
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
|
||||
#if defined ( ARDUINO )
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// If you use SD card, write this.
|
||||
#include <SD.h>
|
||||
|
||||
// If you use SPIFFS, write this.
|
||||
#include <SPIFFS.h>
|
||||
|
||||
#endif
|
||||
|
||||
// * The filesystem header must be included before the display library.
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// If you use ATOM Display, write this.
|
||||
#include <M5AtomDisplay.h>
|
||||
|
||||
// If you use Module Display, write this.
|
||||
#include <M5ModuleDisplay.h>
|
||||
|
||||
// If you use Module RCA, write this.
|
||||
#include <M5ModuleRCA.h>
|
||||
|
||||
// If you use Unit GLASS, write this.
|
||||
#include <M5UnitGLASS.h>
|
||||
|
||||
// If you use Unit GLASS2, write this.
|
||||
#include <M5UnitGLASS2.h>
|
||||
|
||||
// If you use Unit OLED, write this.
|
||||
#include <M5UnitOLED.h>
|
||||
|
||||
// If you use Unit Mini OLED, write this.
|
||||
#include <M5UnitMiniOLED.h>
|
||||
|
||||
// If you use Unit LCD, write this.
|
||||
#include <M5UnitLCD.h>
|
||||
|
||||
// If you use UnitRCA (for Video output), write this.
|
||||
#include <M5UnitRCA.h>
|
||||
|
||||
// * The display header must be included before the M5Unified library.
|
||||
|
||||
//----------------------------------------------------------------
|
||||
|
||||
// Include this to enable the M5 global instance.
|
||||
#include <M5Unified.h>
|
||||
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
auto cfg = M5.config();
|
||||
|
||||
// external display setting. (Pre-include required)
|
||||
cfg.external_display.module_display = true; // default=true. use ModuleDisplay
|
||||
cfg.external_display.atom_display = true; // default=true. use AtomDisplay
|
||||
cfg.external_display.unit_glass = false; // default=true. use UnitGLASS
|
||||
cfg.external_display.unit_glass2 = false; // default=true. use UnitGLASS2
|
||||
cfg.external_display.unit_oled = false; // default=true. use UnitOLED
|
||||
cfg.external_display.unit_mini_oled = false; // default=true. use UnitMiniOLED
|
||||
cfg.external_display.unit_lcd = false; // default=true. use UnitLCD
|
||||
cfg.external_display.unit_rca = false; // default=true. use UnitRCA VideoOutput
|
||||
cfg.external_display.module_rca = false; // default=true. use ModuleRCA VideoOutput
|
||||
|
||||
/*
|
||||
※ Unit OLED, Unit Mini OLED, Unit GLASS2 cannot be distinguished at runtime and may be misidentified as each other.
|
||||
|
||||
※ Display with auto-detection
|
||||
- module_display
|
||||
- atom_display
|
||||
- unit_glass
|
||||
- unit_glass2
|
||||
- unit_oled
|
||||
- unit_mini_oled
|
||||
- unit_lcd
|
||||
|
||||
※ Displays that cannot be auto-detected
|
||||
- module_rca
|
||||
- unit_rca
|
||||
|
||||
※ Note that if you enable a display that cannot be auto-detected,
|
||||
it will operate as if it were connected, even if it is not actually connected.
|
||||
When RCA is enabled, it consumes a lot of memory to allocate the frame buffer.
|
||||
//*/
|
||||
|
||||
|
||||
// Set individual parameters for external displays.
|
||||
// (※ Use only the items you wish to change. Basically, it can be omitted.)
|
||||
#if defined ( __M5GFX_M5ATOMDISPLAY__ ) // setting for ATOM Display.
|
||||
// cfg.atom_display.logical_width = 1280;
|
||||
// cfg.atom_display.logical_height = 720;
|
||||
// cfg.atom_display.output_width = 1280;
|
||||
// cfg.atom_display.output_height = 720;
|
||||
// cfg.atom_display.refresh_rate = 60;
|
||||
// cfg.atom_display.scale_w = 1;
|
||||
// cfg.atom_display.scale_h = 1;
|
||||
// cfg.atom_display.pixel_clock = 74250000;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5MODULEDISPLAY__ ) // setting for Module Display.
|
||||
// cfg.module_display.logical_width = 1280;
|
||||
// cfg.module_display.logical_height = 720;
|
||||
// cfg.module_display.output_width = 1280;
|
||||
// cfg.module_display.output_height = 720;
|
||||
// cfg.module_display.refresh_rate = 60;
|
||||
// cfg.module_display.scale_w = 1;
|
||||
// cfg.module_display.scale_h = 1;
|
||||
// cfg.module_display.pixel_clock = 74250000;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5MODULERCA__ ) // setting for Module RCA.
|
||||
// cfg.module_rca.logical_width = 216;
|
||||
// cfg.module_rca.logical_height = 144;
|
||||
// cfg.module_rca.output_width = 216;
|
||||
// cfg.module_rca.output_height = 144;
|
||||
// cfg.module_rca.signal_type = M5ModuleRCA::signal_type_t::PAL; // NTSC / NTSC_J / PAL_M / PAL_N
|
||||
// cfg.module_rca.use_psram = M5ModuleRCA::use_psram_t::psram_use; // psram_no_use / psram_half_use
|
||||
// cfg.module_rca.pin_dac = GPIO_NUM_26;
|
||||
// cfg.module_rca.output_level = 128;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5UNITRCA__ ) // setting for Unit RCA.
|
||||
// cfg.unit_rca.logical_width = 216;
|
||||
// cfg.unit_rca.logical_height = 144;
|
||||
// cfg.unit_rca.output_width = 216;
|
||||
// cfg.unit_rca.output_height = 144;
|
||||
// cfg.unit_rca.signal_type = M5UnitRCA::signal_type_t::PAL; // NTSC / NTSC_J / PAL_M / PAL_N
|
||||
// cfg.unit_rca.use_psram = M5UnitRCA::use_psram_t::psram_use; // psram_no_use / psram_half_use
|
||||
// cfg.unit_rca.pin_dac = GPIO_NUM_26;
|
||||
// cfg.unit_rca.output_level = 128;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5UNITGLASS__ ) // setting for Unit GLASS.
|
||||
// cfg.unit_glass.pin_sda = GPIO_NUM_21;
|
||||
// cfg.unit_glass.pin_scl = GPIO_NUM_22;
|
||||
// cfg.unit_glass.i2c_addr = 0x3D;
|
||||
// cfg.unit_glass.i2c_freq = 400000;
|
||||
// cfg.unit_glass.i2c_port = I2C_NUM_0;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5UNITGLASS2__ ) // setting for Unit GLASS2.
|
||||
// cfg.unit_glass2.pin_sda = GPIO_NUM_21;
|
||||
// cfg.unit_glass2.pin_scl = GPIO_NUM_22;
|
||||
// cfg.unit_glass2.i2c_addr = 0x3C;
|
||||
// cfg.unit_glass2.i2c_freq = 400000;
|
||||
// cfg.unit_glass2.i2c_port = I2C_NUM_0;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5UNITOLED__ ) // setting for Unit OLED.
|
||||
// cfg.unit_oled.pin_sda = GPIO_NUM_21;
|
||||
// cfg.unit_oled.pin_scl = GPIO_NUM_22;
|
||||
// cfg.unit_oled.i2c_addr = 0x3C;
|
||||
// cfg.unit_oled.i2c_freq = 400000;
|
||||
// cfg.unit_oled.i2c_port = I2C_NUM_0;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5UNITMINIOLED__ ) // setting for Unit Mini OLED.
|
||||
// cfg.unit_mini_oled.pin_sda = GPIO_NUM_21;
|
||||
// cfg.unit_mini_oled.pin_scl = GPIO_NUM_22;
|
||||
// cfg.unit_mini_oled.i2c_addr = 0x3C;
|
||||
// cfg.unit_mini_oled.i2c_freq = 400000;
|
||||
// cfg.unit_mini_oled.i2c_port = I2C_NUM_0;
|
||||
#endif
|
||||
#if defined ( __M5GFX_M5UNITLCD__ ) // setting for Unit LCD.
|
||||
// cfg.unit_lcd.pin_sda = GPIO_NUM_21;
|
||||
// cfg.unit_lcd.pin_scl = GPIO_NUM_22;
|
||||
// cfg.unit_lcd.i2c_addr = 0x3E;
|
||||
// cfg.unit_lcd.i2c_freq = 400000;
|
||||
// cfg.unit_lcd.i2c_port = I2C_NUM_0;
|
||||
#endif
|
||||
|
||||
|
||||
// begin M5Unified.
|
||||
M5.begin(cfg);
|
||||
|
||||
// Get the number of available displays
|
||||
int display_count = M5.getDisplayCount();
|
||||
|
||||
for (int i = 0; i < display_count; ++i) {
|
||||
// All displays are available in M5.Displays.
|
||||
// ※ Note that the order of which displays are numbered is the order in which they are detected, so the order may change.
|
||||
|
||||
int textsize = M5.Displays(i).height() / 60;
|
||||
if (textsize == 0) { textsize = 1; }
|
||||
M5.Displays(i).setTextSize(textsize);
|
||||
M5.Displays(i).printf("No.%d\n", i);
|
||||
}
|
||||
|
||||
|
||||
// If an external display is to be used as the main display, it can be listed in order of priority.
|
||||
M5.setPrimaryDisplayType( {
|
||||
m5::board_t::board_M5ModuleDisplay,
|
||||
m5::board_t::board_M5AtomDisplay,
|
||||
// m5::board_t::board_M5ModuleRCA,
|
||||
// m5::board_t::board_M5UnitGLASS,
|
||||
// m5::board_t::board_M5UnitGLASS2,
|
||||
// m5::board_t::board_M5UnitMiniOLED,
|
||||
// m5::board_t::board_M5UnitOLED,
|
||||
// m5::board_t::board_M5UnitLCD,
|
||||
// m5::board_t::board_M5UnitRCA,
|
||||
} );
|
||||
|
||||
|
||||
// The primary display can be used with M5.Display.
|
||||
M5.Display.print("primary display\n");
|
||||
|
||||
|
||||
// Examine the indexes of a given type of display
|
||||
int index_module_display = M5.getDisplayIndex(m5::board_t::board_M5ModuleDisplay);
|
||||
int index_atom_display = M5.getDisplayIndex(m5::board_t::board_M5AtomDisplay);
|
||||
int index_module_rca = M5.getDisplayIndex(m5::board_t::board_M5ModuleRCA);
|
||||
int index_unit_glass = M5.getDisplayIndex(m5::board_t::board_M5UnitGLASS);
|
||||
int index_unit_glass2 = M5.getDisplayIndex(m5::board_t::board_M5UnitGLASS2);
|
||||
int index_unit_oled = M5.getDisplayIndex(m5::board_t::board_M5UnitOLED);
|
||||
int index_unit_mini_oled = M5.getDisplayIndex(m5::board_t::board_M5UnitMiniOLED);
|
||||
int index_unit_lcd = M5.getDisplayIndex(m5::board_t::board_M5UnitLCD);
|
||||
int index_unit_rca = M5.getDisplayIndex(m5::board_t::board_M5UnitRCA);
|
||||
|
||||
if (index_module_display >= 0) {
|
||||
M5.Displays(index_module_display).print("This is Module Display\n");
|
||||
}
|
||||
if (index_atom_display >= 0) {
|
||||
M5.Displays(index_atom_display).print("This is Atom Display\n");
|
||||
}
|
||||
if (index_module_rca >= 0) {
|
||||
M5.Displays(index_module_rca).print("This is Module RCA\n");
|
||||
}
|
||||
if (index_unit_glass >= 0) {
|
||||
M5.Displays(index_unit_glass).print("This is Unit GLASS\n");
|
||||
}
|
||||
if (index_unit_glass2 >= 0) {
|
||||
M5.Displays(index_unit_glass2).print("This is Unit GLASS2\n");
|
||||
}
|
||||
if (index_unit_oled >= 0) {
|
||||
M5.Displays(index_unit_oled).print("This is Unit OLED\n");
|
||||
}
|
||||
if (index_unit_mini_oled >= 0) {
|
||||
M5.Displays(index_unit_mini_oled ).print("This is Unit Mini OLED\n");
|
||||
}
|
||||
if (index_unit_lcd >= 0) {
|
||||
M5.Displays(index_unit_lcd).print("This is Unit LCD\n");
|
||||
}
|
||||
if (index_unit_rca >= 0) {
|
||||
M5.Displays(index_unit_rca).print("This is Unit RCA\n");
|
||||
}
|
||||
M5.delay(5000);
|
||||
}
|
||||
|
||||
|
||||
// When creating a function for drawing, it can be used universally by accepting a LovyanGFX type as an argument.
|
||||
void draw_function(LovyanGFX* gfx)
|
||||
{
|
||||
int x = rand() % gfx->width();
|
||||
int y = rand() % gfx->height();
|
||||
int r = (gfx->width() >> 4) + 2;
|
||||
uint16_t c = rand();
|
||||
gfx->fillRect(x-r, y-r, r*2, r*2, c);
|
||||
}
|
||||
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.delay(1);
|
||||
|
||||
for (int i = 0; i < M5.getDisplayCount(); ++i) {
|
||||
int x = rand() % M5.Displays(i).width();
|
||||
int y = rand() % M5.Displays(i).height();
|
||||
int r = (M5.Displays(i).width() >> 4) + 2;
|
||||
uint16_t c = rand();
|
||||
M5.Displays(i).fillCircle(x, y, r, c);
|
||||
}
|
||||
|
||||
for (int i = 0; i < M5.getDisplayCount(); ++i) {
|
||||
draw_function(&M5.Displays(i));
|
||||
}
|
||||
}
|
||||
|
||||
// for ESP-IDF compat
|
||||
#if !defined ( ARDUINO ) && defined ( ESP_PLATFORM )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
3574
libraries/M5Unified/examples/Basic/HowToUse/HowToUse.ino
Normal file
3574
libraries/M5Unified/examples/Basic/HowToUse/HowToUse.ino
Normal file
File diff suppressed because it is too large
Load diff
299
libraries/M5Unified/examples/Basic/Imu/Imu.ino
Normal file
299
libraries/M5Unified/examples/Basic/Imu/Imu.ino
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
|
||||
// If you use Unit OLED, write this.
|
||||
// #include <M5UnitOLED.h>
|
||||
|
||||
// If you use Unit LCD, write this.
|
||||
// #include <M5UnitLCD.h>
|
||||
|
||||
|
||||
// Include this to enable the M5 global instance.
|
||||
#include <M5Unified.h>
|
||||
|
||||
// Strength of the calibration operation;
|
||||
// 0: disables calibration.
|
||||
// 1 is weakest and 255 is strongest.
|
||||
static constexpr const uint8_t calib_value = 64;
|
||||
|
||||
|
||||
// This sample code performs calibration by clicking on a button or screen.
|
||||
// After 10 seconds of calibration, the results are stored in NVS.
|
||||
// The saved calibration values are loaded at the next startup.
|
||||
//
|
||||
// === How to calibration ===
|
||||
// ※ Calibration method for Accelerometer
|
||||
// Change the direction of the main unit by 90 degrees
|
||||
// and hold it still for 2 seconds. Repeat multiple times.
|
||||
// It is recommended that as many surfaces as possible be on the bottom.
|
||||
//
|
||||
// ※ Calibration method for Gyro
|
||||
// Simply place the unit on a quiet desk and hold it still.
|
||||
// It is recommended that this be done after the accelerometer calibration.
|
||||
//
|
||||
// ※ Calibration method for geomagnetic sensors
|
||||
// Rotate the main unit slowly in multiple directions.
|
||||
// It is recommended that as many surfaces as possible be oriented to the north.
|
||||
//
|
||||
// Values for extremely large attitude changes are ignored.
|
||||
// During calibration, it is desirable to move the device as gently as possible.
|
||||
|
||||
struct rect_t
|
||||
{
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t w;
|
||||
int32_t h;
|
||||
};
|
||||
|
||||
static constexpr const uint32_t color_tbl[18] =
|
||||
{
|
||||
0xFF0000u, 0xCCCC00u, 0xCC00FFu,
|
||||
0xFFCC00u, 0x00FF00u, 0x0088FFu,
|
||||
0xFF00CCu, 0x00FFCCu, 0x0000FFu,
|
||||
0xFF0000u, 0xCCCC00u, 0xCC00FFu,
|
||||
0xFFCC00u, 0x00FF00u, 0x0088FFu,
|
||||
0xFF00CCu, 0x00FFCCu, 0x0000FFu,
|
||||
};
|
||||
static constexpr const float coefficient_tbl[3] = { 0.5f, (1.0f / 256.0f), (1.0f / 1024.0f) };
|
||||
|
||||
static auto &dsp = (M5.Display);
|
||||
static rect_t rect_graph_area;
|
||||
static rect_t rect_text_area;
|
||||
|
||||
static uint8_t calib_countdown = 0;
|
||||
|
||||
static int prev_xpos[18];
|
||||
|
||||
void drawBar(int32_t ox, int32_t oy, int32_t nx, int32_t px, int32_t h, uint32_t color)
|
||||
{
|
||||
uint32_t bgcolor = (color >> 3) & 0x1F1F1Fu;
|
||||
if (px && ((nx < 0) != (px < 0)))
|
||||
{
|
||||
dsp.fillRect(ox, oy, px, h, bgcolor);
|
||||
px = 0;
|
||||
}
|
||||
if (px != nx)
|
||||
{
|
||||
if ((nx > px) != (nx < 0))
|
||||
{
|
||||
bgcolor = color;
|
||||
}
|
||||
dsp.setColor(bgcolor);
|
||||
dsp.fillRect(nx + ox, oy, px - nx, h);
|
||||
}
|
||||
}
|
||||
|
||||
void drawGraph(const rect_t& r, const m5::imu_data_t& data)
|
||||
{
|
||||
float aw = (128 * r.w) >> 1;
|
||||
float gw = (128 * r.w) / 256.0f;
|
||||
float mw = (128 * r.w) / 1024.0f;
|
||||
int ox = (r.x + r.w)>>1;
|
||||
int oy = r.y;
|
||||
int h = (r.h / 18) * (calib_countdown ? 1 : 2);
|
||||
int bar_count = 9 * (calib_countdown ? 2 : 1);
|
||||
|
||||
dsp.startWrite();
|
||||
for (int index = 0; index < bar_count; ++index)
|
||||
{
|
||||
float xval;
|
||||
if (index < 9)
|
||||
{
|
||||
auto coe = coefficient_tbl[index / 3] * r.w;
|
||||
xval = data.value[index] * coe;
|
||||
}
|
||||
else
|
||||
{
|
||||
xval = M5.Imu.getOffsetData(index - 9) * (1.0f / (1 << 19));
|
||||
}
|
||||
|
||||
// for Linear scale graph.
|
||||
float tmp = xval;
|
||||
|
||||
// The smaller the value, the larger the amount of change in the graph.
|
||||
// float tmp = sqrtf(fabsf(xval * 128)) * (signbit(xval) ? -1 : 1);
|
||||
|
||||
int nx = tmp;
|
||||
int px = prev_xpos[index];
|
||||
if (nx != px)
|
||||
prev_xpos[index] = nx;
|
||||
drawBar(ox, oy + h * index, nx, px, h - 1, color_tbl[index]);
|
||||
}
|
||||
dsp.endWrite();
|
||||
}
|
||||
|
||||
void updateCalibration(uint32_t c, bool clear = false)
|
||||
{
|
||||
calib_countdown = c;
|
||||
|
||||
if (c == 0) {
|
||||
clear = true;
|
||||
}
|
||||
|
||||
if (clear)
|
||||
{
|
||||
memset(prev_xpos, 0, sizeof(prev_xpos));
|
||||
dsp.fillScreen(TFT_BLACK);
|
||||
|
||||
if (c)
|
||||
{ // Start calibration.
|
||||
M5.Imu.setCalibration(calib_value, calib_value, calib_value);
|
||||
// ※ The actual calibration operation is performed each time during M5.Imu.update.
|
||||
//
|
||||
// There are three arguments, which can be specified in the order of Accelerometer, gyro, and geomagnetic.
|
||||
// If you want to calibrate only the Accelerometer, do the following.
|
||||
// M5.Imu.setCalibration(100, 0, 0);
|
||||
//
|
||||
// If you want to calibrate only the gyro, do the following.
|
||||
// M5.Imu.setCalibration(0, 100, 0);
|
||||
//
|
||||
// If you want to calibrate only the geomagnetism, do the following.
|
||||
// M5.Imu.setCalibration(0, 0, 100);
|
||||
}
|
||||
else
|
||||
{ // Stop calibration. (Continue calibration only for the geomagnetic sensor)
|
||||
M5.Imu.setCalibration(0, 0, calib_value);
|
||||
|
||||
// If you want to stop all calibration, write this.
|
||||
// M5.Imu.setCalibration(0, 0, 0);
|
||||
|
||||
// save calibration values.
|
||||
M5.Imu.saveOffsetToNVS();
|
||||
}
|
||||
}
|
||||
|
||||
auto backcolor = (c == 0) ? TFT_BLACK : TFT_BLUE;
|
||||
dsp.fillRect(rect_text_area.x, rect_text_area.y, rect_text_area.w, rect_text_area.h, backcolor);
|
||||
|
||||
if (c)
|
||||
{
|
||||
dsp.setCursor(rect_text_area.x + 2, rect_text_area.y + 1);
|
||||
dsp.setTextColor(TFT_WHITE, TFT_BLUE);
|
||||
dsp.printf("Countdown:%d ", c);
|
||||
}
|
||||
}
|
||||
|
||||
void startCalibration(void)
|
||||
{
|
||||
updateCalibration(10, true);
|
||||
}
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
auto cfg = M5.config();
|
||||
|
||||
// If you want to use external IMU, write this
|
||||
//cfg.external_imu = true;
|
||||
|
||||
M5.begin(cfg);
|
||||
|
||||
const char* name;
|
||||
auto imu_type = M5.Imu.getType();
|
||||
switch (imu_type)
|
||||
{
|
||||
case m5::imu_none: name = "not found"; break;
|
||||
case m5::imu_sh200q: name = "sh200q"; break;
|
||||
case m5::imu_mpu6050: name = "mpu6050"; break;
|
||||
case m5::imu_mpu6886: name = "mpu6886"; break;
|
||||
case m5::imu_mpu9250: name = "mpu9250"; break;
|
||||
case m5::imu_bmi270: name = "bmi270"; break;
|
||||
default: name = "unknown"; break;
|
||||
};
|
||||
M5_LOGI("imu:%s", name);
|
||||
M5.Display.printf("imu:%s", name);
|
||||
|
||||
if (imu_type == m5::imu_none)
|
||||
{
|
||||
for (;;) { delay(1); }
|
||||
}
|
||||
|
||||
int32_t w = dsp.width();
|
||||
int32_t h = dsp.height();
|
||||
if (w < h)
|
||||
{
|
||||
dsp.setRotation(dsp.getRotation() ^ 1);
|
||||
w = dsp.width();
|
||||
h = dsp.height();
|
||||
}
|
||||
int32_t graph_area_h = ((h - 8) / 18) * 18;
|
||||
int32_t text_area_h = h - graph_area_h;
|
||||
float fontsize = text_area_h / 8;
|
||||
dsp.setTextSize(fontsize);
|
||||
|
||||
rect_graph_area = { 0, 0, w, graph_area_h };
|
||||
rect_text_area = {0, graph_area_h, w, text_area_h };
|
||||
|
||||
|
||||
// Read calibration values from NVS.
|
||||
if (!M5.Imu.loadOffsetFromNVS())
|
||||
{
|
||||
startCalibration();
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
static uint32_t frame_count = 0;
|
||||
static uint32_t prev_sec = 0;
|
||||
|
||||
// To update the IMU value, use M5.Imu.update.
|
||||
// If a new value is obtained, the return value is non-zero.
|
||||
auto imu_update = M5.Imu.update();
|
||||
if (imu_update)
|
||||
{
|
||||
// Obtain data on the current value of the IMU.
|
||||
auto data = M5.Imu.getImuData();
|
||||
drawGraph(rect_graph_area, data);
|
||||
/*
|
||||
// The data obtained by getImuData can be used as follows.
|
||||
data.accel.x; // accel x-axis value.
|
||||
data.accel.y; // accel y-axis value.
|
||||
data.accel.z; // accel z-axis value.
|
||||
data.accel.value; // accel 3values array [0]=x / [1]=y / [2]=z.
|
||||
|
||||
data.gyro.x; // gyro x-axis value.
|
||||
data.gyro.y; // gyro y-axis value.
|
||||
data.gyro.z; // gyro z-axis value.
|
||||
data.gyro.value; // gyro 3values array [0]=x / [1]=y / [2]=z.
|
||||
|
||||
data.mag.x; // mag x-axis value.
|
||||
data.mag.y; // mag y-axis value.
|
||||
data.mag.z; // mag z-axis value.
|
||||
data.mag.value; // mag 3values array [0]=x / [1]=y / [2]=z.
|
||||
|
||||
data.value; // all sensor 9values array [0~2]=accel / [3~5]=gyro / [6~8]=mag
|
||||
|
||||
M5_LOGV("ax:%f ay:%f az:%f", data.accel.x, data.accel.y, data.accel.z);
|
||||
M5_LOGV("gx:%f gy:%f gz:%f", data.gyro.x , data.gyro.y , data.gyro.z );
|
||||
M5_LOGV("mx:%f my:%f mz:%f", data.mag.x , data.mag.y , data.mag.z );
|
||||
//*/
|
||||
++frame_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
M5.update();
|
||||
|
||||
// Calibration is initiated when a button or screen is clicked.
|
||||
if (M5.BtnA.wasClicked() || M5.BtnPWR.wasClicked() || M5.Touch.getDetail().wasClicked())
|
||||
{
|
||||
startCalibration();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t sec = millis() / 1000;
|
||||
if (prev_sec != sec)
|
||||
{
|
||||
prev_sec = sec;
|
||||
M5_LOGI("sec:%d frame:%d", sec, frame_count);
|
||||
frame_count = 0;
|
||||
|
||||
if (calib_countdown)
|
||||
{
|
||||
updateCalibration(calib_countdown - 1);
|
||||
}
|
||||
|
||||
if ((sec & 7) == 0)
|
||||
{ // prevent WDT.
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
133
libraries/M5Unified/examples/Basic/LogOutput/LogOutput.ino
Normal file
133
libraries/M5Unified/examples/Basic/LogOutput/LogOutput.ino
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
#include <M5Unified.h>
|
||||
|
||||
|
||||
void user_made_log_callback(esp_log_level_t, bool, const char*);
|
||||
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
/// Example of ESP32 standard log output macro usage.
|
||||
/// ESP_LOGx series outputs to USB-connected PC terminal.
|
||||
/// You can set the output level with `Core Debug Level` in ArduinoIDE.
|
||||
/// ※ If the `Core Debug Level` is set to `None`, nothing is output.
|
||||
#if defined ( ESP_PLATFORM )
|
||||
ESP_LOGE("TAG", "using ESP_LOGE error log."); // Critical errors, software module can not recover on its own
|
||||
ESP_LOGW("TAG", "using ESP_LOGW warn log."); // Error conditions from which recovery measures have been taken
|
||||
ESP_LOGI("TAG", "using ESP_LOGI info log."); // Information messages which describe normal flow of events
|
||||
ESP_LOGD("TAG", "using ESP_LOGD debug log."); // Extra information which is not necessary for normal use (values, pointers, sizes, etc).
|
||||
ESP_LOGV("TAG", "using ESP_LOGV verbose log."); // Bigger chunks of debugging information, or frequent messages which can potentially flood the output.
|
||||
#endif
|
||||
|
||||
M5.begin();
|
||||
|
||||
/// If you want to output logs to the display, write this.
|
||||
M5.setLogDisplayIndex(0);
|
||||
|
||||
/// use wrapping from bottom edge to top edge.
|
||||
M5.Display.setTextWrap(true, true);
|
||||
/// use scrolling.
|
||||
// M5.Display.setTextScroll(true);
|
||||
|
||||
/// Example of M5Unified log output class usage.
|
||||
/// Unlike ESP_LOGx, the M5.Log series can output to serial, display, and user callback function in a single line of code.
|
||||
|
||||
|
||||
/// You can set Log levels for each output destination.
|
||||
/// ESP_LOG_ERROR / ESP_LOG_WARN / ESP_LOG_INFO / ESP_LOG_DEBUG / ESP_LOG_VERBOSE
|
||||
M5.Log.setLogLevel(m5::log_target_serial, ESP_LOG_VERBOSE);
|
||||
M5.Log.setLogLevel(m5::log_target_display, ESP_LOG_DEBUG);
|
||||
M5.Log.setLogLevel(m5::log_target_callback, ESP_LOG_INFO);
|
||||
|
||||
/// Set up user-specific callback functions.
|
||||
M5.Log.setCallback(user_made_log_callback);
|
||||
|
||||
/// You can color the log or not.
|
||||
M5.Log.setEnableColor(m5::log_target_serial, true);
|
||||
M5.Log.setEnableColor(m5::log_target_display, true);
|
||||
M5.Log.setEnableColor(m5::log_target_callback, true);
|
||||
|
||||
/// You can set the text to be added to the end of the log for each output destination.
|
||||
/// ( default value : "\n" )
|
||||
M5.Log.setSuffix(m5::log_target_serial, "\n");
|
||||
M5.Log.setSuffix(m5::log_target_display, "\n");
|
||||
M5.Log.setSuffix(m5::log_target_callback, "");
|
||||
|
||||
/// `M5.Log()` can be used to output a simple log
|
||||
M5.Log(ESP_LOG_ERROR , "M5.Log error log"); /// ERROR level output
|
||||
M5.Log(ESP_LOG_WARN , "M5.Log warn log"); /// WARN level output
|
||||
M5.Log(ESP_LOG_INFO , "M5.Log info log"); /// INFO level output
|
||||
M5.Log(ESP_LOG_DEBUG , "M5.Log debug log"); /// DEBUG level output
|
||||
M5.Log(ESP_LOG_VERBOSE , "M5.Log verbose log"); /// VERBOSE level output
|
||||
|
||||
/// `M5_LOGx` macro can be used to output a log containing the source file name, line number, and function name.
|
||||
M5_LOGE("M5_LOGE error log"); /// ERROR level output with source info
|
||||
M5_LOGW("M5_LOGW warn log"); /// WARN level output with source info
|
||||
M5_LOGI("M5_LOGI info log"); /// INFO level output with source info
|
||||
M5_LOGD("M5_LOGD debug log"); /// DEBUG level output with source info
|
||||
M5_LOGV("M5_LOGV verbose log"); /// VERBOSE level output with source info
|
||||
|
||||
/// `M5.Log.printf()` is output without log level and without suffix and is output to all serial, display, and callback.
|
||||
M5.Log.printf("M5.Log.printf non level output\n");
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.delay(1);
|
||||
M5.update();
|
||||
|
||||
if (M5.BtnPWR.wasClicked()) { M5_LOGE("BtnP %d click", M5.BtnPWR.getClickCount()); }
|
||||
if (M5.BtnA .wasClicked()) { M5_LOGW("BtnA %d click", M5.BtnA .getClickCount()); }
|
||||
if (M5.BtnB .wasClicked()) { M5_LOGI("BtnB %d click", M5.BtnB .getClickCount()); }
|
||||
if (M5.BtnC .wasClicked()) { M5_LOGD("BtnC %d click", M5.BtnC .getClickCount()); }
|
||||
|
||||
static uint32_t counter = 0;
|
||||
if ((++counter & 0x3FF) == 0)
|
||||
{
|
||||
static int prev_y;
|
||||
int cursor_y = M5.Display.getCursorY();
|
||||
if (prev_y > cursor_y)
|
||||
{
|
||||
M5.Display.clear();
|
||||
}
|
||||
prev_y = cursor_y;
|
||||
M5_LOGV("count:%d", counter >> 10);
|
||||
}
|
||||
}
|
||||
|
||||
void user_made_log_callback(esp_log_level_t log_level, bool use_color, const char* log_text)
|
||||
{
|
||||
// You can also create your own callback function to output log contents to a file,WiFi,and more other destination
|
||||
|
||||
#if defined ( ARDUINO )
|
||||
/*
|
||||
if (SD.begin(GPIO_NUM_4, SPI, 25000000))
|
||||
{
|
||||
auto file = SD.open("/logfile.txt", FILE_APPEND);
|
||||
file.print(log_text);
|
||||
file.close();
|
||||
SD.end();
|
||||
}
|
||||
//*/
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/// for ESP-IDF
|
||||
#if !defined ( ARDUINO ) && defined ( ESP_PLATFORM )
|
||||
extern "C"
|
||||
{
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
145
libraries/M5Unified/examples/Basic/Microphone/Microphone.ino
Normal file
145
libraries/M5Unified/examples/Basic/Microphone/Microphone.ino
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#include <M5UnitLCD.h>
|
||||
#include <M5UnitOLED.h>
|
||||
#include <M5Unified.h>
|
||||
|
||||
static constexpr const size_t record_number = 256;
|
||||
static constexpr const size_t record_length = 200;
|
||||
static constexpr const size_t record_size = record_number * record_length;
|
||||
static constexpr const size_t record_samplerate = 16000;
|
||||
static int16_t prev_y[record_length];
|
||||
static int16_t prev_h[record_length];
|
||||
static size_t rec_record_idx = 2;
|
||||
static size_t draw_record_idx = 0;
|
||||
static int16_t *rec_data;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
auto cfg = M5.config();
|
||||
|
||||
// cfg.external_speaker.hat_spk = true; /// use external speaker (HAT SPK)
|
||||
// cfg.external_speaker.hat_spk2 = true; /// use external speaker (HAT SPK2)
|
||||
// cfg.external_speaker.atomic_spk = true; /// use external speaker (ATOMIC SPK)
|
||||
|
||||
M5.begin(cfg);
|
||||
|
||||
M5.Display.startWrite();
|
||||
|
||||
if (M5.Display.width() > M5.Display.height())
|
||||
{
|
||||
M5.Display.setRotation(M5.Display.getRotation()^1);
|
||||
}
|
||||
|
||||
M5.Display.setCursor(0, 0);
|
||||
M5.Display.print("REC");
|
||||
rec_data = (typeof(rec_data))heap_caps_malloc(record_size * sizeof(int16_t), MALLOC_CAP_8BIT);
|
||||
memset(rec_data, 0 , record_size * sizeof(int16_t));
|
||||
M5.Speaker.setVolume(255);
|
||||
|
||||
/// Since the microphone and speaker cannot be used at the same time, turn off the speaker here.
|
||||
M5.Speaker.end();
|
||||
M5.Mic.begin();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.update();
|
||||
|
||||
if (M5.Mic.isEnabled())
|
||||
{
|
||||
static constexpr int shift = 6;
|
||||
auto data = &rec_data[rec_record_idx * record_length];
|
||||
if (M5.Mic.record(data, record_length, record_samplerate))
|
||||
{
|
||||
data = &rec_data[draw_record_idx * record_length];
|
||||
|
||||
int32_t w = M5.Display.width();
|
||||
if (w > record_length - 1) { w = record_length - 1; }
|
||||
for (int32_t x = 0; x < w; ++x)
|
||||
{
|
||||
M5.Display.writeFastVLine(x, prev_y[x], prev_h[x], TFT_BLACK);
|
||||
int32_t y1 = (data[x ] >> shift);
|
||||
int32_t y2 = (data[x + 1] >> shift);
|
||||
if (y1 > y2)
|
||||
{
|
||||
int32_t tmp = y1;
|
||||
y1 = y2;
|
||||
y2 = tmp;
|
||||
}
|
||||
int32_t y = (M5.Display.height() >> 1) + y1;
|
||||
int32_t h = (M5.Display.height() >> 1) + y2 + 1 - y;
|
||||
prev_y[x] = y;
|
||||
prev_h[x] = h;
|
||||
M5.Display.writeFastVLine(x, y, h, TFT_WHITE);
|
||||
}
|
||||
M5.Display.display();
|
||||
|
||||
if (++draw_record_idx >= record_number) { draw_record_idx = 0; }
|
||||
if (++rec_record_idx >= record_number) { rec_record_idx = 0; }
|
||||
}
|
||||
}
|
||||
|
||||
if (M5.BtnA.wasHold() || M5.BtnB.wasClicked())
|
||||
{
|
||||
auto cfg = M5.Mic.config();
|
||||
cfg.noise_filter_level = (cfg.noise_filter_level + 8) & 255;
|
||||
M5.Mic.config(cfg);
|
||||
M5.Display.setCursor(32,0);
|
||||
M5.Display.printf("nf:%03d", cfg.noise_filter_level);
|
||||
}
|
||||
else
|
||||
if (M5.BtnA.wasClicked() || (M5.Touch.getCount() && M5.Touch.getDetail(0).wasClicked()))
|
||||
{
|
||||
if (M5.Speaker.isEnabled())
|
||||
{
|
||||
M5.Display.clear();
|
||||
while (M5.Mic.isRecording()) { M5.delay(1); }
|
||||
|
||||
/// Since the microphone and speaker cannot be used at the same time, turn off the microphone here.
|
||||
M5.Mic.end();
|
||||
M5.Speaker.begin();
|
||||
|
||||
M5.Display.setCursor(0,0);
|
||||
M5.Display.print("PLAY");
|
||||
int start_pos = rec_record_idx * record_length;
|
||||
if (start_pos < record_size)
|
||||
{
|
||||
M5.Speaker.playRaw(&rec_data[start_pos], record_size - start_pos, record_samplerate, false, 1, 0);
|
||||
}
|
||||
if (start_pos > 0)
|
||||
{
|
||||
M5.Speaker.playRaw(rec_data, start_pos, record_samplerate, false, 1, 0);
|
||||
}
|
||||
do
|
||||
{
|
||||
M5.delay(1);
|
||||
M5.update();
|
||||
} while (M5.Speaker.isPlaying());
|
||||
|
||||
/// Since the microphone and speaker cannot be used at the same time, turn off the speaker here.
|
||||
M5.Speaker.end();
|
||||
M5.Mic.begin();
|
||||
|
||||
M5.Display.clear();
|
||||
M5.Display.setCursor(0,0);
|
||||
M5.Display.print("REC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined ( ARDUINO )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
155
libraries/M5Unified/examples/Basic/Rtc/Rtc.ino
Normal file
155
libraries/M5Unified/examples/Basic/Rtc/Rtc.ino
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#if defined ( ARDUINO )
|
||||
|
||||
#define WIFI_SSID "YOUR WIFI SSID NAME"
|
||||
#define WIFI_PASSWORD "YOUR WIFI PASSWORD"
|
||||
#define NTP_TIMEZONE "JST-9"
|
||||
#define NTP_SERVER1 "0.pool.ntp.org"
|
||||
#define NTP_SERVER2 "1.pool.ntp.org"
|
||||
#define NTP_SERVER3 "2.pool.ntp.org"
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
// Different versions of the framework have different SNTP header file names and availability.
|
||||
#if __has_include (<esp_sntp.h>)
|
||||
#include <esp_sntp.h>
|
||||
#define SNTP_ENABLED 1
|
||||
#elif __has_include (<sntp.h>)
|
||||
#include <sntp.h>
|
||||
#define SNTP_ENABLED 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef SNTP_ENABLED
|
||||
#define SNTP_ENABLED 0
|
||||
#endif
|
||||
|
||||
#include <M5Unified.h>
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
auto cfg = M5.config();
|
||||
|
||||
cfg.external_rtc = true; // default=false. use Unit RTC.
|
||||
|
||||
M5.begin(cfg);
|
||||
|
||||
M5.Display.setEpdMode(m5gfx::epd_fastest);
|
||||
M5.setLogDisplayIndex(0);
|
||||
|
||||
if (!M5.Rtc.isEnabled())
|
||||
{
|
||||
M5.Log.println("RTC not found.");
|
||||
for (;;) { M5.delay(500); }
|
||||
}
|
||||
|
||||
M5.Log.println("RTC found.");
|
||||
|
||||
// It is recommended to set UTC for the RTC and ESP32 internal clocks.
|
||||
|
||||
|
||||
/* /// setup RTC ( direct setting )
|
||||
// YYYY MM DD hh mm ss
|
||||
M5.Rtc.setDateTime( { { 2021, 12, 31 }, { 12, 34, 56 } } );
|
||||
//*/
|
||||
|
||||
|
||||
/// setup RTC ( NTP auto setting )
|
||||
configTzTime(NTP_TIMEZONE, NTP_SERVER1, NTP_SERVER2, NTP_SERVER3);
|
||||
#ifdef WiFi_h
|
||||
M5.Log.print("WiFi:");
|
||||
WiFi.begin( WIFI_SSID, WIFI_PASSWORD );
|
||||
|
||||
for (int i = 20; i && WiFi.status() != WL_CONNECTED; --i)
|
||||
{
|
||||
M5.Log.print(".");
|
||||
M5.delay(500);
|
||||
}
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
M5.Log.println("\r\nWiFi Connected.");
|
||||
M5.Log.print("NTP:");
|
||||
#if SNTP_ENABLED
|
||||
while (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED)
|
||||
{
|
||||
M5.Log.print(".");
|
||||
M5.delay(1000);
|
||||
}
|
||||
#else
|
||||
M5.delay(1600);
|
||||
struct tm timeInfo;
|
||||
while (!getLocalTime(&timeInfo, 1000))
|
||||
{
|
||||
M5.Log.print('.');
|
||||
};
|
||||
#endif
|
||||
M5.Log.println("\r\nNTP Connected.");
|
||||
|
||||
time_t t = time(nullptr)+1; // Advance one second.
|
||||
while (t > time(nullptr)); /// Synchronization in seconds
|
||||
M5.Rtc.setDateTime( gmtime( &t ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
M5.Log.println("\r\nWiFi none...");
|
||||
}
|
||||
#endif
|
||||
|
||||
M5.Display.clear();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
static constexpr const char* const wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
|
||||
|
||||
M5.delay(500);
|
||||
|
||||
auto dt = M5.Rtc.getDateTime();
|
||||
M5.Display.setCursor(0,0);
|
||||
M5.Log.printf("RTC UTC :%04d/%02d/%02d (%s) %02d:%02d:%02d\r\n"
|
||||
, dt.date.year
|
||||
, dt.date.month
|
||||
, dt.date.date
|
||||
, wd[dt.date.weekDay]
|
||||
, dt.time.hours
|
||||
, dt.time.minutes
|
||||
, dt.time.seconds
|
||||
);
|
||||
|
||||
/// ESP32 internal timer
|
||||
auto t = time(nullptr);
|
||||
{
|
||||
auto tm = gmtime(&t); // for UTC.
|
||||
M5.Display.setCursor(0,20);
|
||||
M5.Log.printf("ESP32 UTC :%04d/%02d/%02d (%s) %02d:%02d:%02d\r\n",
|
||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
|
||||
wd[tm->tm_wday],
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
|
||||
{
|
||||
auto tm = localtime(&t); // for local timezone.
|
||||
M5.Display.setCursor(0,40);
|
||||
M5.Log.printf("ESP32 %s:%04d/%02d/%02d (%s) %02d:%02d:%02d\r\n", NTP_TIMEZONE,
|
||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
|
||||
wd[tm->tm_wday],
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined ( ARDUINO )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
17724
libraries/M5Unified/examples/Basic/Speaker/Speaker.ino
Normal file
17724
libraries/M5Unified/examples/Basic/Speaker/Speaker.ino
Normal file
File diff suppressed because it is too large
Load diff
164
libraries/M5Unified/examples/Basic/Touch/DragDrop/DragDrop.ino
Normal file
164
libraries/M5Unified/examples/Basic/Touch/DragDrop/DragDrop.ino
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#include <M5Unified.h>
|
||||
|
||||
struct box_t
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
std::uint16_t color;
|
||||
int touch_id = -1;
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
M5.Display.setColor(M5.Display.getBaseColor());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
M5.Display.drawRect(x+i, y+i, w-i*2, h-i*2);
|
||||
}
|
||||
}
|
||||
void draw(void)
|
||||
{
|
||||
M5.Display.setColor(color);
|
||||
int ie = touch_id < 0 ? 4 : 8;
|
||||
for (int i = 0; i < ie; ++i)
|
||||
{
|
||||
M5.Display.drawRect(x+i, y+i, w-i*2, h-i*2);
|
||||
}
|
||||
}
|
||||
bool contain(int x, int y)
|
||||
{
|
||||
return this->x <= x && x < (this->x + this->w)
|
||||
&& this->y <= y && y < (this->y + this->h);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr std::size_t box_count = 4;
|
||||
static box_t box_list[box_count];
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
for (std::size_t i = 0; i < box_count; ++i)
|
||||
{
|
||||
box_list[i].w = 100;
|
||||
box_list[i].h = 100;
|
||||
}
|
||||
box_list[0].x = 0;
|
||||
box_list[0].y = 0;
|
||||
box_list[1].x = M5.Display.width() - box_list[1].w;
|
||||
box_list[1].y = 0;
|
||||
box_list[2].x = 0;
|
||||
box_list[2].y = M5.Display.height() - box_list[2].h;
|
||||
box_list[3].x = M5.Display.width() - box_list[3].w;
|
||||
box_list[3].y = M5.Display.height() - box_list[3].h;
|
||||
box_list[0].color = TFT_RED;
|
||||
box_list[1].color = TFT_BLUE;
|
||||
box_list[2].color = TFT_GREEN;
|
||||
box_list[3].color = TFT_YELLOW;
|
||||
|
||||
M5.Display.setEpdMode(epd_mode_t::epd_fastest);
|
||||
M5.Display.startWrite();
|
||||
M5.Display.setTextSize(2);
|
||||
for (std::size_t i = 0; i < box_count; ++i)
|
||||
{
|
||||
box_list[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.delay(1);
|
||||
|
||||
M5.update();
|
||||
|
||||
auto count = M5.Touch.getCount();
|
||||
if (!count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static m5::touch_state_t prev_state;
|
||||
auto t = M5.Touch.getDetail();
|
||||
if (prev_state != t.state)
|
||||
{
|
||||
prev_state = t.state;
|
||||
static constexpr const char* state_name[16] =
|
||||
{ "none"
|
||||
, "touch"
|
||||
, "touch_end"
|
||||
, "touch_begin"
|
||||
, "___"
|
||||
, "hold"
|
||||
, "hold_end"
|
||||
, "hold_begin"
|
||||
, "___"
|
||||
, "flick"
|
||||
, "flick_end"
|
||||
, "flick_begin"
|
||||
, "___"
|
||||
, "drag"
|
||||
, "drag_end"
|
||||
, "drag_begin"
|
||||
};
|
||||
M5_LOGI("%s", state_name[t.state]);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < count; ++i)
|
||||
{
|
||||
auto t = M5.Touch.getDetail(i);
|
||||
|
||||
for (std::size_t j = 0; j < box_count; ++j)
|
||||
{
|
||||
if (t.wasHold())
|
||||
{
|
||||
if (box_list[j].contain(t.x, t.y))
|
||||
{
|
||||
box_list[j].touch_id = t.id;
|
||||
}
|
||||
}
|
||||
|
||||
M5.Display.waitDisplay();
|
||||
if (box_list[j].touch_id == t.id)
|
||||
{
|
||||
if (t.wasReleased())
|
||||
{
|
||||
box_list[j].touch_id = -1;
|
||||
box_list[j].clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dx = t.deltaX();
|
||||
auto dy = t.deltaY();
|
||||
if (dx || dy)
|
||||
{
|
||||
box_list[j].clear();
|
||||
box_list[j].x += dx;
|
||||
box_list[j].y += dy;
|
||||
}
|
||||
}
|
||||
}
|
||||
box_list[j].draw();
|
||||
}
|
||||
}
|
||||
M5.Display.display();
|
||||
}
|
||||
|
||||
#if !defined ( ARDUINO ) && defined ( ESP_PLATFORM )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
228
libraries/M5Unified/examples/Basic/Touch/SliderUI/SliderUI.ino
Normal file
228
libraries/M5Unified/examples/Basic/Touch/SliderUI/SliderUI.ino
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
#include <M5Unified.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct rect_t
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
|
||||
bool contain(int x, int y)
|
||||
{
|
||||
return this->x <= x && x < (this->x + this->w)
|
||||
&& this->y <= y && y < (this->y + this->h);
|
||||
}
|
||||
bool contain(m5::Touch_Class::point_t &p) {
|
||||
return contain(p.x, p.y);
|
||||
}
|
||||
};
|
||||
|
||||
class slider_t
|
||||
{
|
||||
public:
|
||||
void setup(const rect_t &r, int min_value, int max_value, int value, uint16_t frame_color = 0xFFFF, uint16_t back_color = 0, uint16_t thumb_color = 0xFFE0) {
|
||||
setupPosition(r);
|
||||
setupValue(min_value, max_value, value);
|
||||
setupColor(frame_color, back_color, thumb_color);
|
||||
}
|
||||
|
||||
void setupPosition(const rect_t &r) {
|
||||
_rect = r;
|
||||
_vertical = r.h > r.w;
|
||||
}
|
||||
|
||||
void setupValue(int min_value, int max_value, int value)
|
||||
{
|
||||
_min_value = min_value;
|
||||
_max_value = max_value;
|
||||
_current_value = value;
|
||||
_control_value = value;
|
||||
}
|
||||
|
||||
void setupColor(uint16_t frame_color, uint16_t back_color, uint16_t thumb_color)
|
||||
{
|
||||
_frame_color = frame_color;
|
||||
_back_color = back_color;
|
||||
_thumb_color = thumb_color;
|
||||
}
|
||||
|
||||
void draw(LovyanGFX* gfx = &M5.Display)
|
||||
{
|
||||
gfx->startWrite();
|
||||
draw_frame(gfx);
|
||||
int pos = calc_pos(_current_value);
|
||||
draw_thumb(pos, _thumb_color, gfx);
|
||||
gfx->endWrite();
|
||||
}
|
||||
|
||||
bool update(m5::touch_detail_t &td, LovyanGFX* gfx = &M5.Display)
|
||||
{
|
||||
_was_changed = false;
|
||||
if (!_rect.contain(td.base)) return false;
|
||||
|
||||
if (td.wasReleased()) {
|
||||
_current_value = _control_value;
|
||||
}
|
||||
|
||||
if (td.isPressed()) {
|
||||
int rw = _vertical ? _rect.h : _rect.w;
|
||||
int tmp = (_current_value - _min_value) * rw / (_max_value - _min_value);
|
||||
tmp += _vertical ? td.distanceY() : td.distanceX();
|
||||
int v = _min_value + (_max_value - _min_value) * tmp / rw;
|
||||
_was_changed = value_update(v, gfx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getValue(void) const { return _control_value; }
|
||||
bool wasChanged(void) const { return _was_changed; }
|
||||
|
||||
protected:
|
||||
rect_t _rect;
|
||||
|
||||
int _min_value;
|
||||
int _max_value;
|
||||
int _current_value;
|
||||
int _control_value;
|
||||
|
||||
uint16_t _frame_color = 0xFFFF;
|
||||
uint16_t _back_color = 0;
|
||||
uint16_t _thumb_color = 0xFFE0;
|
||||
bool _vertical = false;
|
||||
bool _was_changed = false;
|
||||
|
||||
bool value_update(int new_value, LovyanGFX* gfx = &M5.Display)
|
||||
{
|
||||
int min_v = _min_value;
|
||||
int max_v = _max_value;
|
||||
if (min_v > max_v) {
|
||||
min_v = _max_value;
|
||||
max_v = _min_value;
|
||||
}
|
||||
new_value = new_value < min_v ? min_v : new_value > max_v ? max_v : new_value;
|
||||
|
||||
if (_control_value == new_value) {
|
||||
return false;
|
||||
}
|
||||
int prev_pos = calc_pos(_control_value);
|
||||
int new_pos = calc_pos(new_value);
|
||||
_control_value = new_value;
|
||||
|
||||
if (prev_pos != new_pos) {
|
||||
gfx->startWrite();
|
||||
draw_thumb(prev_pos, _back_color, gfx);
|
||||
draw_thumb(new_pos, _thumb_color, gfx);
|
||||
gfx->endWrite();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int calc_pos(int value)
|
||||
{
|
||||
int diff = _max_value - _min_value;
|
||||
if (diff == 0) return 0;
|
||||
value -= _min_value;
|
||||
int w = _vertical ? (_rect.h - _rect.w) : (_rect.w - _rect.h);
|
||||
return (w * value) / diff;
|
||||
}
|
||||
|
||||
void draw_frame(LovyanGFX* gfx = &M5.Display)
|
||||
{
|
||||
gfx->fillRoundRect(_rect.x+1, _rect.y+1, _rect.w-2, _rect.h-2, 2, _back_color);
|
||||
gfx->drawRoundRect(_rect.x, _rect.y, _rect.w, _rect.h, 3, _frame_color);
|
||||
}
|
||||
|
||||
void draw_thumb(int pos, uint16_t color, LovyanGFX* gfx = &M5.Display)
|
||||
{
|
||||
int rx = _rect.x + 1;
|
||||
int ry = _rect.y + 1;
|
||||
int rw;
|
||||
if (_vertical) {
|
||||
ry += pos;
|
||||
rw = _rect.w;
|
||||
} else {
|
||||
rx += pos;
|
||||
rw = _rect.h;
|
||||
}
|
||||
rw -= 2;
|
||||
gfx->fillRoundRect(rx, ry, rw, rw, 3, color);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static constexpr std::size_t slider_count = 4;
|
||||
static slider_t slider_list[slider_count];
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
int dw = M5.Display.width();
|
||||
int dh = M5.Display.height();
|
||||
|
||||
slider_list[0].setup({ 20, dh/2 -20, dw-40, 40 }, 5, 25, 15, TFT_WHITE, TFT_BLACK, TFT_LIGHTGRAY);
|
||||
slider_list[1].setup({ dw*1/4-20, 0, 40, dh/2 -40 }, 255, 0, 127, TFT_WHITE, TFT_BLACK, TFT_RED);
|
||||
slider_list[2].setup({ dw*2/4-20, 0, 40, dh/2 -40 }, 255, 0, 127, TFT_WHITE, TFT_BLACK, TFT_GREEN);
|
||||
slider_list[3].setup({ dw*3/4-20, 0, 40, dh/2 -40 }, 255, 0, 127, TFT_WHITE, TFT_BLACK, TFT_BLUE);
|
||||
|
||||
M5.Display.setEpdMode(epd_mode_t::epd_fastest);
|
||||
M5.Display.setTextSize(2);
|
||||
for (std::size_t i = 0; i < slider_count; ++i)
|
||||
{
|
||||
slider_list[i].draw();
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
M5.delay(16);
|
||||
|
||||
M5.update();
|
||||
|
||||
if (0 == M5.Touch.getCount())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
auto t = M5.Touch.getDetail();
|
||||
for (std::size_t i = 0; i < slider_count; ++i)
|
||||
{
|
||||
if (slider_list[i].update(t)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
int w = slider_list[0].getValue();
|
||||
int r = slider_list[1].getValue();
|
||||
int g = slider_list[2].getValue();
|
||||
int b = slider_list[3].getValue();
|
||||
uint32_t rgb = r << 16 | g << 8 | b;
|
||||
if (slider_list[0].wasChanged())
|
||||
{
|
||||
M5.Display.fillRect(M5.Display.width()/2-25, M5.Display.height()*3/4-25, 51,51, TFT_BLACK);
|
||||
}
|
||||
M5.Display.fillCircle(M5.Display.width()/2, M5.Display.height()*3/4, w, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined ( ARDUINO ) && defined ( ESP_PLATFORM )
|
||||
extern "C" {
|
||||
void loopTask(void*)
|
||||
{
|
||||
setup();
|
||||
for (;;) {
|
||||
loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue