#ifndef PT_TASK_H
#define PT_TASK_H

#include "pt.h"

#include "pt_sem.h"

#include "pt_ext.h"

#include "pt_pm.h"

/*
 * Structure for registered entries
 * Contains the name, protothread control structure, and function pointers
 * for initialization and entry functions.
 */
typedef struct pt pt_t;

typedef struct
{
    const char      name[24];       /* Entry name */
    pt_t*           pt;                /* Protothread control structure */ 
    int             status;    
    int (*fn_entry)(pt_t *pt);         /* Function pointer */
} pt_task_t;


/*
 * Register a scheduling entry function
 * \param obj_name Unique identifier for the entry (max 7 chars)
 * \param pt_ptr Protothread control structure pointer
 * \param entry_func Entry point function (int (*)(pt_t *))
 */
/*
 * Register a scheduling entry function
 * @param obj_name Unique identifier for the entry (max 7 chars)
 * @param pt_ptr Protothread control structure pointer
 * @param init_func Initialization function (int (*)(pt_t *))
 * @param entry_func Entry point function (int (*)(pt_t *))
 */
#define PT_TASK_OBJ(obj_name)      _pt_task_object_##obj_name
    
//#define PT_TASK_OBJ_DECL(obj_name) pt_task_t PT_TASK_OBJ(obj_name)


/*
 * Specific section boundary accessors for PT_SCHEDULE_SECTION
 */
#ifdef __CC_ARM
    /* MDK ARM Compiler specific macros for PT_SCHEDULE_SECTION */
    #define PT_TASK_OBJ_START ((uint32_t)&PT_TASK_OBJ(start))
    #define PT_TASK_OBJ_END ((uint32_t)&PT_TASK_OBJ(end))
#elif defined(__GNUC__)
    extern char __start_PT_SCHEDULE[];
    extern char __stop_PT_SCHEDULE[];
    #define PT_SCHEDULE_START  (uint32_t)__start_PT_SCHEDULE
    #define PT_SCHEDULE_END    (uint32_t)__stop_PT_SCHEDULE
#endif


#define PT_TASK_DECL(obj_name,level,entry_func) \
    static pt_t      _pt_object_##obj_name; \
    static pt_task_t _pt_task_object_##obj_name\
        __attribute__((section("task._pt_obj_"#level), used)) = { \
            .name = #obj_name, \
            .pt = &(_pt_object_##obj_name), \
            .fn_entry =(entry_func) \
        }


#define PT_TASK_START(entry_func)           PT_TASK_DECL(start,"00",entry_func)
        
#define PT_TASK_BOARD_REG(entry_func)       PT_TASK_DECL(entry_func,"01",entry_func)
                                                       
#define PT_TASK_DRIVER_REG(entry_func)      PT_TASK_DECL(entry_func,"02",entry_func)
                                                         
#define PT_TASK_DEVICE_REG(entry_func)      PT_TASK_DECL(entry_func,"03",entry_func)
                                                        
#define PT_TASK_COMPONENT_REG(entry_func)   PT_TASK_DECL(entry_func,"04",entry_func)
                                                       
#define PT_TASK_THID_REG(entry_func)        PT_TASK_DECL(entry_func,"05",entry_func)
                                                       
#define PT_TASK_APP_REG(entry_func)         PT_TASK_DECL(entry_func,"06",entry_func)

#define PT_TASK_END(entry_func)             PT_TASK_DECL(end,"99",entry_func)

/*
 * Prototypes for auto management functions
 */
void pt_task_init(void);

void pt_task_schedule(void);
 
bool pt_task_is_active(pt_task_t *task);
        
bool pt_task_all_idle(void);

#endif


