
#include "pt_task.h"
#include "pt_pm.h"
#include "pt_ext.h"

#include "stdio.h"

// 系统空闲条件
#define SYSTEM_IS_IDLE() (ALL_TASKS_IDLE())
#define DEEP_SLEEP_THRESHOLD  5      // 进入深度休眠的空闲计数阈值
    
static struct {
    pm_adapter_t default_adapter;
    pt_t pt;
    pm_mode_t current_mode; // 当前功耗模式
    uint32_t ref_count[PM_SLEEP_MODE_MAX]; // 引用计数数组
} pm;

static bool system_is_idle(void)
{
   return pt_task_all_idle();
}

/*
功耗管理：遍历所有任务状态，然后根据用于请求的功耗模式，调用适配器接口，调整MCU的运行模式
*/
static void pt_pm_handler(void) {
    
    if (system_is_idle()) {

        // 切换到下一个可用的功耗模式
        pm_mode_t next_mode = PM_SLEEP_MODE_NONE;
        for (pm_mode_t m = PM_SLEEP_MODE_NONE; m < PM_SLEEP_MODE_MAX; m++) {
            if (pm.ref_count[m] > 0 ) {
                next_mode = m;
            }
        }

        if (next_mode != pm.current_mode && pm.default_adapter.sleep) {
            pm.default_adapter.sleep(next_mode);
            pm.current_mode = next_mode;
        }
        
    } else {
        
        pt_pm_release(PM_SLEEP_MODE_NONE); // 唤醒系统

        if (pm.default_adapter.wakeup) {
            pm.default_adapter.wakeup();
        }
        pm.current_mode = PM_SLEEP_MODE_NONE;
    }
}


void pt_pm_adapter_init(pm_adapter_t *adapter) {
    if (adapter) {
        pm.default_adapter = *adapter; // 复制整个结构体
    } else {
        pm.default_adapter.sleep = 0;
        pm.default_adapter.wakeup = 0;
    }
}

void pt_pm_init(void) {
    
    PT_INIT(&pm.pt);
}


int  pt_task_pm(void) {
    
    PT_BEGIN(&pm.pt);
    
    while (1) {
        
        pt_pm_handler(); // 处理功耗状态
       
        PT_DELAY_MS(&pm.pt, system_is_idle() ? 1000 : 100);
    }
    
    PT_END(&pm.pt);
}

/*
请求功耗模式：引用计数自增，如果为1，则调用适配器接口，调整MCU的运行模式
*/
void pt_pm_request(pm_mode_t mode) {
    if (mode >= PM_SLEEP_MODE_MAX) {
        return; // 无效模式
    }
    pm.ref_count[mode]++; // 仅操作引用计数
}

/*
释放功耗模式：引用计数自减，如果为0，则调用适配器接口，调整MCU的运行模式
*/
void pt_pm_release(pm_mode_t mode) {
    if (mode >= PM_SLEEP_MODE_MAX) {
        return; // 无效模式
    }
    if (pm.ref_count[mode] > 0) {
        pm.ref_count[mode]--; // 仅操作引用计数
    }
}
