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
2 changes: 1 addition & 1 deletion idf_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ description: Unified library for M5Stack series
issues: https://github.com/m5stack/M5Unified/issues
repository: https://github.com/m5stack/M5Unified.git
url: https://github.com/m5stack/M5Unified.git
version: 0.2.24
version: 0.2.25
dependencies:
m5stack/m5gfx:
version: ">=0.2.31"
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"version": ">=0.2.31"
}
],
"version": "0.2.24",
"version": "0.2.25",
"frameworks": ["arduino", "espidf", "*"],
"platforms": ["espressif32", "native"],
"headers": "M5Unified.h"
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=M5Unified
version=0.2.24
version=0.2.25
author=M5Stack
maintainer=M5Stack
sentence=Unified library for M5Stack series
Expand Down
18 changes: 15 additions & 3 deletions src/M5Unified.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,16 @@ namespace m5
// Boards where GPIO46 is exposed to the application (camera VSYNC on CoreS3, camera data on
// AtomS3R Cam, header pin on StampS3 / AtomS3R Ext) get the pad restored once the board is
// known, see below.
// Skipped when the application already ran Display.init(): GPIO46 may then carry the display
// bus (StopWatch QSPI io2), which this output would overwrite. The hold is applied below,
// once the pin map is known, only on boards that use GPIO46 as their power hold.
const bool gpio46_hold = (Display.getBoard() == m5gfx::board_t::board_unknown);
m5gfx::gpio::pin_backup_t gpio46_backup(GPIO_NUM_46);
m5gfx::gpio_hi(GPIO_NUM_46);
m5gfx::pinMode(GPIO_NUM_46, m5gfx::pin_mode_t::output);
if (gpio46_hold)
{
m5gfx::gpio_hi(GPIO_NUM_46);
m5gfx::pinMode(GPIO_NUM_46, m5gfx::pin_mode_t::output);
}
#endif

auto brightness = Display.getBrightness();
Expand All @@ -376,10 +383,15 @@ namespace m5
_board = board;
_setup_pinmap(board);
#if defined ( CONFIG_IDF_TARGET_ESP32S3 )
if (!gpio46_hold && getPin(pin_name_t::power_hold) == GPIO_NUM_46)
{
m5gfx::gpio_hi(GPIO_NUM_46);
m5gfx::pinMode(GPIO_NUM_46, m5gfx::pin_mode_t::output);
}
// Restore only on boards positively identified as exposing GPIO46 to the application
// (camera VSYNC / data, header pin); every other case (power hold, display bus pins
// configured by Display.init(), a fallback board) keeps the previous behaviour.
switch (board_detected ? board : board_t::board_unknown)
switch (board_detected && gpio46_hold ? board : board_t::board_unknown)
{
case board_t::board_M5StackCoreS3:
case board_t::board_M5StackCoreS3SE:
Expand Down
26 changes: 11 additions & 15 deletions src/M5Unified.inl
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,7 @@ static constexpr const uint8_t _pin_table_i2c_ex_in[][5] = {
{ board_t::board_M5StampC5 , 255 ,255 , 255 ,255 },
{ board_t::board_M5ToughC5 , GPIO_NUM_3 ,GPIO_NUM_2 , GPIO_NUM_3 ,GPIO_NUM_2 }, // PortA は内部バスと同一 (レベルシフタ経由の物理分配)
{ board_t::board_unknown , 255 ,255 , 255 ,255 },
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
{ board_t::board_unknown , 255 ,255 , 255 ,255 },
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
{ board_t::board_M5Stack , GPIO_NUM_22,GPIO_NUM_21 , GPIO_NUM_22,GPIO_NUM_21 },
{ board_t::board_M5Paper , GPIO_NUM_22,GPIO_NUM_21 , GPIO_NUM_32,GPIO_NUM_25 },
{ board_t::board_M5TimerCam , GPIO_NUM_14,GPIO_NUM_12 , GPIO_NUM_13,GPIO_NUM_4 },
Expand All @@ -157,6 +155,10 @@ static constexpr const uint8_t _pin_table_i2c_ex_in[][5] = {
{ board_t::board_M5AtomU , GPIO_NUM_21,GPIO_NUM_25 , GPIO_NUM_32,GPIO_NUM_26 },
{ board_t::board_M5AtomPsram , GPIO_NUM_21,GPIO_NUM_25 , GPIO_NUM_32,GPIO_NUM_26 },
{ board_t::board_unknown , GPIO_NUM_22,GPIO_NUM_21 , GPIO_NUM_33,GPIO_NUM_32 }, // Core2,Tough,StickC,CoreInk,Station,StampPico
#else
// A chip without boards of its own: nothing to probe. Kept explicit so that it never
// inherits the ESP32 table above.
{ board_t::board_unknown , 255 ,255 , 255 ,255 },
#endif
};

Expand All @@ -180,8 +182,7 @@ static constexpr const uint8_t _pin_table_port_bc[][5] = {
{ board_t::board_M5Tab5 , GPIO_NUM_17,GPIO_NUM_52, GPIO_NUM_7 ,GPIO_NUM_6 }, // Tab5
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
{ board_t::board_M5ToughC5 , GPIO_NUM_1 ,GPIO_NUM_6 , GPIO_NUM_12,GPIO_NUM_11 },
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
{ board_t::board_M5Stack , GPIO_NUM_36,GPIO_NUM_26 , GPIO_NUM_16,GPIO_NUM_17 },
{ board_t::board_M5StackCore2 , GPIO_NUM_36,GPIO_NUM_26 , GPIO_NUM_13,GPIO_NUM_14 },
{ board_t::board_M5Tough , GPIO_NUM_36,GPIO_NUM_26 , GPIO_NUM_13,GPIO_NUM_14 },
Expand All @@ -202,8 +203,7 @@ static constexpr const uint8_t _pin_table_port_de[][5] = {
#elif defined (CONFIG_IDF_TARGET_ESP32C61)
#elif defined (CONFIG_IDF_TARGET_ESP32H2)
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
{ board_t::board_M5Stack , GPIO_NUM_34,GPIO_NUM_35 , GPIO_NUM_5 ,GPIO_NUM_13 },
{ board_t::board_M5StackCore2 , GPIO_NUM_34,GPIO_NUM_35 , GPIO_NUM_27,GPIO_NUM_19 },
{ board_t::board_M5Station , GPIO_NUM_36,GPIO_NUM_26 , GPIO_NUM_16,GPIO_NUM_17 }, // B2 / C2
Expand Down Expand Up @@ -235,8 +235,7 @@ static constexpr const uint8_t _pin_table_sd[][7] = {
{ board_t::board_M5Tab5 , GPIO_NUM_43, GPIO_NUM_44, GPIO_NUM_39, GPIO_NUM_40, GPIO_NUM_41, GPIO_NUM_42 },
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
{ board_t::board_M5ToughC5 , GPIO_NUM_9 , GPIO_NUM_7 , GPIO_NUM_8 , 255 , 255 , GPIO_NUM_10 },
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
{ board_t::board_M5Stack , GPIO_NUM_18, GPIO_NUM_23, GPIO_NUM_19, 255 , 255 , GPIO_NUM_4 },
{ board_t::board_M5StackCore2 , GPIO_NUM_18, GPIO_NUM_23, GPIO_NUM_38, 255 , 255 , GPIO_NUM_4 },
{ board_t::board_M5Tough , GPIO_NUM_18, GPIO_NUM_23, GPIO_NUM_38, 255 , 255 , GPIO_NUM_4 },
Expand Down Expand Up @@ -269,8 +268,7 @@ static constexpr const uint8_t _pin_table_other0[][2] = {
#elif defined (CONFIG_IDF_TARGET_ESP32H2)
{ board_t::board_M5NanoH2 , GPIO_NUM_11 },
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
{ board_t::board_M5Stack , GPIO_NUM_15 },
{ board_t::board_M5StackCore2 , GPIO_NUM_25 },
{ board_t::board_M5Station , GPIO_NUM_4 },
Expand Down Expand Up @@ -298,8 +296,7 @@ static constexpr const uint8_t _pin_table_other1[][2] = {
#elif defined (CONFIG_IDF_TARGET_ESP32C61)
#elif defined (CONFIG_IDF_TARGET_ESP32H2)
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)

{ board_t::board_M5StickCPlus2 , GPIO_NUM_4 },
{ board_t::board_M5Paper , GPIO_NUM_2 },
Expand Down Expand Up @@ -420,8 +417,7 @@ static constexpr const uint8_t _pin_table_mbus[][31] = {
},
#elif defined (CONFIG_IDF_TARGET_ESP32H2)
#elif defined (CONFIG_IDF_TARGET_ESP32C5)
#elif defined (CONFIG_IDF_TARGET_ESP32S2)
#else
#elif !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
{ board_t::board_M5Stack ,
255 , GPIO_NUM_35,
255 , GPIO_NUM_36,
Expand Down
2 changes: 1 addition & 1 deletion src/gitTagVersion.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#define M5UNIFIED_VERSION_MAJOR 0
#define M5UNIFIED_VERSION_MINOR 2
#define M5UNIFIED_VERSION_PATCH 24
#define M5UNIFIED_VERSION_PATCH 25
#define M5UNIFIED_VERSION F( M5UNIFIED_VERSION_MAJOR "." M5UNIFIED_VERSION_MINOR "." M5UNIFIED_VERSION_PATCH )
35 changes: 20 additions & 15 deletions src/utility/Mic_Class.inl
Original file line number Diff line number Diff line change
Expand Up @@ -317,13 +317,18 @@ namespace m5
if (_cfg.pin_bck < 0 || _cfg.pin_ws < 0) {
i2s_pdm_rx_config_t i2s_config;
memset(&i2s_config, 0, sizeof(i2s_pdm_rx_config_t));
#if defined ( CONFIG_IDF_TARGET_ESP32P4 ) || defined (CONFIG_IDF_TARGET_ESP32H2)
i2s_config.clk_cfg.clk_src = i2s_clock_src_t::I2S_CLK_SRC_DEFAULT;
#else
i2s_config.clk_cfg.clk_src = i2s_clock_src_t::I2S_CLK_SRC_PLL_160M;
#endif
#if defined ( M5UNIFIED_I2S_PLL_D2_HZ )
i2s_config.clk_cfg.sample_rate_hz = 48000; // dummy setting
i2s_config.clk_cfg.mclk_multiple = i2s_mclk_multiple_t::I2S_MCLK_MULTIPLE_128; // dummy setting
#else
// No verified raw clock recipe on this chip: the driver keeps the clock, so the real
// port rate (over_sampling included, as the capture task expects) goes in here.
// DSR 16 matches what the raw path selects.
i2s_config.clk_cfg.sample_rate_hz = _calc_rec_rate();
i2s_config.clk_cfg.mclk_multiple = i2s_mclk_multiple_t::I2S_MCLK_MULTIPLE_256;
i2s_config.clk_cfg.dn_sample_mode = i2s_pdm_dsr_t::I2S_PDM_DSR_16S;
#endif
i2s_config.slot_cfg.data_bit_width = i2s_data_bit_width_t::I2S_DATA_BIT_WIDTH_16BIT;
i2s_config.slot_cfg.slot_bit_width = i2s_slot_bit_width_t::I2S_SLOT_BIT_WIDTH_16BIT;
i2s_config.slot_cfg.slot_mode = (_cfg.stereo) ? i2s_slot_mode_t::I2S_SLOT_MODE_STEREO : i2s_slot_mode_t::I2S_SLOT_MODE_MONO;
Expand All @@ -336,14 +341,9 @@ if (_cfg.pin_bck < 0 || _cfg.pin_ws < 0) {
{
i2s_std_config_t i2s_config;
memset(&i2s_config, 0, sizeof(i2s_std_config_t));
#if defined ( CONFIG_IDF_TARGET_ESP32P4 ) || defined (CONFIG_IDF_TARGET_ESP32H2)
i2s_config.clk_cfg.clk_src = i2s_clock_src_t::I2S_CLK_SRC_DEFAULT;
#else
i2s_config.clk_cfg.clk_src = i2s_clock_src_t::I2S_CLK_SRC_PLL_160M;
#endif
#if defined ( CONFIG_IDF_TARGET_ESP32P4 )
{ // ESP32-P4 はクロックをドライバ管理で最終値に確定させる (mic_task での raw 分周
// 上書きを行わない)。クロック源既定 (minimum supported revision < 3 のビルドは
#if M5UNIFIED_I2S_DRIVER_MANAGED_CLK
{ // クロックをドライバ管理で最終値に確定させる (mic_task での raw 分周上書きを行わない)。クロック源既定 (minimum supported revision < 3 のビルドは
// XTAL 40MHz / rev >= 3 ビルドは PLL_F160M) もドライバに委ねる。
int os = _cfg.over_sampling;
if (os < 1) { os = 1; } else if (os > 8) { os = 8; }
Expand Down Expand Up @@ -458,6 +458,7 @@ if (_cfg.pin_bck < 0 || _cfg.pin_ws < 0) {

bool use_pdm = (self->_cfg.pin_bck < 0 && !self->_cfg.use_adc);

#if defined ( M5UNIFIED_I2S_PLL_D2_HZ )
static constexpr uint32_t PLL_D2_CLK = M5UNIFIED_I2S_PLL_D2_HZ;

uint32_t bits = (self->_cfg.use_adc) ? 1 : 16; /// 1サンプリング当たりの出力ビット数;
Expand All @@ -473,6 +474,7 @@ if (_cfg.pin_bck < 0 || _cfg.pin_ws < 0) {
// read here: a queued record() with a new rate may overwrite it while
// this request is still being captured.
calcClockDiv(&div_a, &div_b, &div_n, PLL_D2_CLK / (bits * div_m), self->_rec_sample_rate);
#endif

// false when the raw clock latch below times out: the channel must not
// report itself active with an unlatched clock configuration.
Expand All @@ -489,7 +491,10 @@ if (_cfg.pin_bck < 0 || _cfg.pin_ws < 0) {
#endif
#endif

#if defined (M5UNIFIED_I2S_HW_V2)
#if !defined ( M5UNIFIED_I2S_PLL_D2_HZ )
// No verified raw recipe for this chip: the driver keeps the mode and clock it configured.
(void)dev; (void)use_pdm;
#elif defined (M5UNIFIED_I2S_HW_V2)

dev->rx_conf.rx_pdm_en = use_pdm;
dev->rx_conf.rx_tdm_en = !use_pdm;
Expand All @@ -500,9 +505,9 @@ if (_cfg.pin_bck < 0 || _cfg.pin_ws < 0) {
dev->rx_conf.rx_pdm2pcm_en = use_pdm;
dev->rx_conf.rx_pdm_sinc_dsr_16_en = 1;
#endif
#if defined (CONFIG_IDF_TARGET_ESP32P4)
// ESP32-P4 の std 経路はクロックを _setup_i2s でドライバ管理により最終値に
// 設定済みのため、raw 分周の上書きを行わない (PDM 経路は従来どおり)。
#if M5UNIFIED_I2S_DRIVER_MANAGED_CLK
// std 経路はクロックを _setup_i2s でドライバ管理により最終値に設定済みのため、
// raw 分周の上書きを行わない (PDM 経路は従来どおり)。
const bool skip_raw_clk = !use_pdm;
#else
const bool skip_raw_clk = false;
Expand Down
3 changes: 3 additions & 0 deletions src/utility/Power_Class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,12 @@ namespace m5
void setLed(uint8_t brightness = 255);

/// all power off.
/// @note PowerHub enters light sleep after requesting power-off and restarts if it wakes.
void powerOff(void);

/// sleep and timer boot. The boot condition can be specified by the argument.
/// @note PowerHub paces alarm writes by 50 ms, settles for 500 ms before requesting
/// power-off, then enters light sleep and restarts if it wakes.
/// @param seconds Number of seconds to boot.
void timerSleep(int seconds);

Expand Down
17 changes: 12 additions & 5 deletions src/utility/Power_Class.inl
Original file line number Diff line number Diff line change
Expand Up @@ -1693,11 +1693,18 @@ namespace m5

#if defined (CONFIG_IDF_TARGET_ESP32S3)
case board_t::board_M5PowerHub:
uint8_t buf[6]={};
M5.In_I2C.writeRegister(powerhub_i2c_addr, 0x00, buf, sizeof(buf), i2c_freq);
M5.In_I2C.writeRegister8(powerhub_i2c_addr, 0xE0, 1, i2c_freq);
use_deepsleep = false;
break;
{
// The STM32 arms the RTC alarm asynchronously after acknowledging the writes.
// Let it finish before the power-off request can overtake the alarm update.
static constexpr uint32_t powerhub_alarm_settle_ms = 500;
if (withTimer) { m5gfx::delay(powerhub_alarm_settle_ms); }
uint8_t buf[6]={};
M5.In_I2C.writeRegister(powerhub_i2c_addr, 0x00, buf, sizeof(buf), i2c_freq);
M5.In_I2C.writeRegister8(powerhub_i2c_addr, 0xE0, 1, i2c_freq);
// Do not resume the sketch with outputs off and the alarm still armed.
use_deepsleep = false;
break;
}
#endif
}

Expand Down
16 changes: 7 additions & 9 deletions src/utility/Speaker_Class.inl
Original file line number Diff line number Diff line change
Expand Up @@ -202,14 +202,12 @@ namespace m5

i2s_std_config_t i2s_config;
memset(&i2s_config, 0, sizeof(i2s_std_config_t));
#if defined ( CONFIG_IDF_TARGET_ESP32H2 ) || defined ( CONFIG_IDF_TARGET_ESP32P4 )
// On every chip whose raw divider path runs (M5UNIFIED_I2S_PLL_D2_HZ), I2S_CLK_SRC_DEFAULT
// is the PLL_160M source that path expects, so no chip list is needed here. (The ESP32-P4
// default is chosen at run time, which is why its clock stays driver managed.)
i2s_config.clk_cfg.clk_src = i2s_clock_src_t::I2S_CLK_SRC_DEFAULT;
#else
i2s_config.clk_cfg.clk_src = i2s_clock_src_t::I2S_CLK_SRC_PLL_160M;
#endif
#if defined ( CONFIG_IDF_TARGET_ESP32P4 )
// ESP32-P4 はクロックをドライバ管理で最終値に確定させる (spk_task での raw 分周
// 上書きを行わない)。ここで実レートを渡すことで、begin 中のクロック遷移が
#if M5UNIFIED_I2S_DRIVER_MANAGED_CLK
// クロックをドライバ管理で最終値に確定させる (spk_task での raw 分周上書きを行わない)。ここで実レートを渡すことで、begin 中のクロック遷移が
// 一度きりになり、外付け codec (Tab5=ES8388) のロック失敗を防ぐ。
// クロック源既定 (minimum supported revision < 3 のビルドは XTAL 40MHz /
// rev >= 3 ビルドは PLL_F160M) もドライバに委ねる。
Expand Down Expand Up @@ -400,7 +398,7 @@ namespace m5
#else
const i2s_port_t i2s_port = self->_cfg.i2s_port;

#if defined (CONFIG_IDF_TARGET_ESP32P4)
#if M5UNIFIED_I2S_DRIVER_MANAGED_CLK
// クロックは _setup_i2s でドライバ管理により最終値に設定済み (実レート +
// 256fs、40MHz source ビルドの高レートのみ 128fs)。
// ドライバの分数分周 (a/b ≤ 511) は十分高精度のため、レート換算は公称値でよい。
Expand Down Expand Up @@ -537,7 +535,7 @@ namespace m5
dev->conf.tx_fifo_reset = 0;

#endif
#endif // !CONFIG_IDF_TARGET_ESP32P4 (raw クロック設定ブロック全体)
#endif // !M5UNIFIED_I2S_DRIVER_MANAGED_CLK (raw クロック設定ブロック全体)
// i2s_zero_dma_buffer(i2s_port);

enum spk_i2s_state
Expand Down
26 changes: 16 additions & 10 deletions src/utility/m5unified_i2s.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,25 @@
/// Source clock frequency assumed by the raw clock divider setup in the speaker/mic
/// tasks (the frequency selected by tx/rx_clk_sel = 1 on HW v2, PLL_160M on HW v1).
/// This is a per-chip physical property that cannot be derived from a capability
/// macro, so every known target is enumerated explicitly.
/// macro, so it is only defined for the targets on which it has been verified; on
/// any other chip the raw divider is not written and the driver keeps the clock it
/// configured (M5UNIFIED_I2S_DRIVER_MANAGED_CLK).
#if defined ( CONFIG_IDF_TARGET_ESP32C3 ) || defined ( CONFIG_IDF_TARGET_ESP32C6 ) || defined ( CONFIG_IDF_TARGET_ESP32C5 ) || defined ( CONFIG_IDF_TARGET_ESP32C61 ) || defined ( CONFIG_IDF_TARGET_ESP32S3 )
#define M5UNIFIED_I2S_PLL_D2_HZ (120*1000*1000) // 240 MHz/2
#elif defined ( CONFIG_IDF_TARGET_ESP32P4 )
#define M5UNIFIED_I2S_PLL_D2_HZ (20*1000*1000) // 20 MHz
#elif defined ( CONFIG_IDF_TARGET_ESP32H2 ) || defined ( CONFIG_IDF_TARGET_ESP32H4 )
#define M5UNIFIED_I2S_PLL_D2_HZ (20*1000*1000) // 20 MHz (PDM capture only; the std path is driver managed)
#elif defined ( CONFIG_IDF_TARGET_ESP32H2 )
#define M5UNIFIED_I2S_PLL_D2_HZ (96*1000*1000) // PLL_F96M
#else
/// Unknown I2S-capable targets fall back to the HW v1 value. The message below is
/// intentionally not #warning (which fails -Werror builds); it flags that the
/// frequency must be verified and added to the table above.
#if defined (M5UNIFIED_I2S_PORT_COUNT) && defined (CONFIG_IDF_TARGET) && !defined (CONFIG_IDF_TARGET_ESP32) && !defined (CONFIG_IDF_TARGET_ESP32S2)
#pragma message ("M5Unified: unknown target, assuming a 80 MHz I2S source clock. Verify it and extend the table in m5unified_i2s.h")
#endif
#elif !defined ( CONFIG_IDF_TARGET ) || defined ( CONFIG_IDF_TARGET_ESP32 ) || defined ( CONFIG_IDF_TARGET_ESP32S2 )
#define M5UNIFIED_I2S_PLL_D2_HZ (80*1000*1000) // 160 MHz/2
#endif

/// The speaker/mic std paths leave the sample clock to the driver (real rate passed at
/// setup, no raw divider override) on chips whose clock tree the raw path has not been
/// verified against, and on ESP32-P4 where the one-shot clock transition is required
/// by the external codec.
#if defined ( CONFIG_IDF_TARGET_ESP32P4 ) || !defined ( M5UNIFIED_I2S_PLL_D2_HZ )
#define M5UNIFIED_I2S_DRIVER_MANAGED_CLK 1
#else
#define M5UNIFIED_I2S_DRIVER_MANAGED_CLK 0
#endif
15 changes: 12 additions & 3 deletions src/utility/rtc/RTC_PowerHub_Class.inl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

namespace m5
{
// The STM32 applies D0..D3 from its main loop after acknowledging I2C writes.
// Pace the writes so an older update cannot clear the pending flag for a newer one.
static constexpr std::uint32_t powerhub_alarm_apply_wait_ms = 50;

static std::uint8_t weekdayToPowerHub(std::int8_t weekDay)
{
static constexpr std::uint8_t weekDayTable[] = { 1, 2, 4, 8, 10, 20, 40 };
Expand Down Expand Up @@ -113,21 +117,24 @@ namespace m5

}
}
if (date->date >= 0)
// A time-only alarm has no date; zero in D2 means every day.
if (date && date->date >= 0)
{
irq_enable = true;
buf[2] = date->date & 0x1f;
}

writeRegister(0xD0, buf, 3);
m5gfx::delay(powerhub_alarm_apply_wait_ms);

if (irq_enable) {
bitOn(0xB0, irq_enable);
bitOn(0xD3, irq_enable);
} else {
bitOff(0xB0, irq_enable);
bitOff(0xD3, irq_enable);
writeRegister8(0xD3, 0); // A zero bit mask would leave the alarm enabled.
}
m5gfx::delay(powerhub_alarm_apply_wait_ms);

return irq_enable;
}
Expand All @@ -142,11 +149,13 @@ namespace m5
if (!_init) { return; }
static constexpr const std::uint8_t buf[4] = {};
writeRegister(0xD0, buf, sizeof(buf));
m5gfx::delay(powerhub_alarm_apply_wait_ms);
}

void RTC_PowerHub_Class::disableIRQ(void)
{
if (!_init) { return; }
bitOff(0xD3, 0); // disable alarm
writeRegister8(0xD3, 0); // Clear the enable register; bitOff with a zero mask is a no-op.
m5gfx::delay(powerhub_alarm_apply_wait_ms);
}
}
Loading