/*******************************************************************************
* Project:      Amped'RF Bluetooth
* File name:    SDK_BP_Signals.h
* Description:  BP Signals
*
* Copyright (c) 2016 Amped'RF Technology Inc, All rights reserved.
*******************************************************************************/

#ifndef BACKPLANE_H
#define BACKPLANE_H

#define BP_KERNEL_TID             0x0000
#define BP_IDLE_TID               0x0000
#define BP_ISR_TID                0xFFFD // Used for simulations
#define BP_INVALID_TID            0xFFFF
#define BP_INVALID_MID            0xFFFF
#define BP_INVALID_PRIO           0xFFFF
#define BP_INVALID_SIGNAL_NUMBER  0xFFFF

#define BP_HIGH_PRIO              0x40
#define BP_DEFAULT_PRIO           0x80
#define BP_LOW_PRIO               0xC0
#define BP_IDLE_PRIO              0xFF

#define BP_JOB_DONE               (true)
#define BP_JOB_PENDING            (false)


//------------------------------------------------------------------------------
//
//  Macros
//
//------------------------------------------------------------------------------

// Get the signal number from the head.
// Note: Please do NOT access the head directly.
#define BP_GetSignalNo(pSignal)      ((pSignal)->Head.SignalNumber)

// Get a pointer to the first byte in the data.
#define BP_GetSignalDataPtr(pSignal) (&((pSignal)->Data.Byte[0]))

// Critical section
#define BP_InitCriticalSection(CS)  (BP_InitMutex(CS))
#define BP_EnterCriticalSection(CS) (BP_LockMutex(CS, true))
#define BP_ExitCriticalSection(CS)  (BP_UnlockMutex(CS))

// Macro for declaring a memory pool
// $$$-JL: Obsolete! To be removed!
#define BP_DECLARE_POOL(Pool, NoOfBlocks, BlockSize) \
  tBP_MemBlockPtr Pool[(sizeof(tBP_Pool) + \
                       NoOfBlocks * (((BlockSize+3)&0xFFFFFFFC) + sizeof(tBP_MemBlock))) / \
                       sizeof(tBP_MemBlockPtr)]
// $$$-JL: Obsolete! To be removed!
#define BP_DECLARE_MEM_POOL(Pool, NoOfBlocks, BlockSize) \
  tBP_MemBlockPtr Pool[(sizeof(tBP_Pool) + \
                       NoOfBlocks * (((BlockSize+3)&0xFFFFFFFC) + sizeof(tBP_MemBlock))) / \
                       sizeof(tBP_MemBlockPtr)]

// Macro for declaring a heap
#define BP_DECLARE_HEAP(Heap, Size)  char Heap[Size]

// Macros for checking execution mode

// Macros used for debug purposes
#ifdef MAGIC_DEBUG
#define BP_DECLARE_MAGIC_NUMBER(var)   uint32 var;
#else
#define BP_DECLARE_MAGIC_NUMBER(var)
#endif //MAGIC_DEBUG


//------------------------------------------------------------------------------
//  Types
//------------------------------------------------------------------------------
typedef uint16 tBP_TaskId;
typedef uint16 tBP_TaskPrio;
typedef uint16 tBP_DataSize;
//typedef uint32 tBP_SignalNo;
//typedef uint32 tOS_SignalNo;
typedef char*  tBP_TaskName;
typedef char*  tBP_Name;
typedef uint16 tBP_ModuleId;
typedef uint8* tBP_StackPtr;

/*
// Please do not access this data structure from outside.
// It is here because it is needed in the tBP_Signal declaration
typedef struct tBP_SignalHead {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber)
  tBP_SignalNo       SignalNumber;
  tBP_TaskId         SenderTaskId;
  tBP_TaskId         OwnerTaskId;
  tBP_DataSize       DataSize;
#ifdef BP_CHECK_SIGNALS
  uint8              CheckTraverse;
#endif
  struct tBP_Signal *pNextSignal;
} tBP_SignalHead;

typedef struct tBP_Signal {
  tOS_SignalHead Head;
  tOS_SignalData Data;
} tBP_Signal, *tpBP_Signal;
*/

#define tBP_Signal      tOS_Signal
#define tpBP_Signal     tpOS_Signal



// Forward declaration
struct tBP_Pool;

// Callback function for mem pool
typedef void (*tBP_PoolNotifyFunc)(struct tBP_Pool*);

// Memory Block Pointer (double pointer)
typedef void *tBP_MemBlockPtr;

// Memory Block Head
typedef struct tBP_MemBlock {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber)
#ifdef MEMTRACKING
  uint32 BlockTrack;
  uint32 Timestamp;
#endif
  struct tBP_Pool     *pOwnerPool;
  struct tBP_MemBlock *pNext;
  struct tBP_MemBlock *pMemHeader;
} tBP_MemBlock, *tpBP_MemBlock;

// Memory Pool
typedef struct tBP_Pool {
  char                *Name;
  uint32               NoOfBlocks;
  uint32               BlockSize;
  uint32               BlockUse;
  uint32               BlockUsePeak;
  void *               TopAddress;
  tBP_PoolNotifyFunc   NotifyFunc;
  struct tBP_Pool     *pNextPool;
  tpBP_MemBlock        pFreeBlock;
} tBP_Pool, *tpBP_Pool, tBP_MemPool, *tpBP_MemPool;

// Memory Block Queue
typedef struct tBP_Queue {
  tpBP_MemBlock pFirst;
  tpBP_MemBlock pLast;
  uint16        Count;
  uint16        Limit;
} tBP_Queue, *tpBP_Queue;

// Heap Block Head
typedef struct tBP_HeapBlockHead {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber)
  uint16                Size;
  tBP_TaskId            TaskId;
} tBP_HeapBlockHead, *tpBP_HeapBlockHead;

// Memory Block Head
typedef struct tBP_HeapBlock {
  tBP_HeapBlockHead     Head;
  struct tBP_HeapBlock *pNextBlock;
} tBP_HeapBlock, *tpBP_HeapBlock;

// Memory Pool
typedef struct tBP_Heap {
  char                *Name;
  uint32               Size;
  struct tBP_Heap     *pNextHeap;
  uint16              *pSizeTable;
  tpBP_HeapBlock      *pBlockTable;
  tpBP_HeapBlock       pFreeBlock;
} tBP_Heap, *tpBP_Heap;

// Memory Type
typedef enum {
  eBP_XRam,
  eBP_IRam,
  eBP_BRam,
  eBP_AnyRam
} tBP_MemType, tBP_MemLocation; // $$$-JL: Obsolete! To be removed!

// Memory Allocation Result
// $$$-JL: Obsolete! To be removed!
typedef struct {
  void   *pMem;
  uint32 AlloctedSize;
} tBP_ReqMemInfo;

// Task Context
typedef struct tBP_TaskContext {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber1)
  struct tBP_TaskContext *pNext;
  tBP_TaskId              TaskId;
  uint16                  StackSize;
  tBP_StackPtr            StackPtr;
  BP_DECLARE_MAGIC_NUMBER(MagicNumber2)
} tBP_TaskContext, *tpBP_TaskContext;

// Mutex
typedef struct {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber)
  tpBP_TaskContext  pFirst;
  tpBP_TaskContext  pLast;
  tBP_TaskId        OwnerTaskId;
  uint16            LocksCount;
} tBP_Mutex, *tpBP_Mutex, tBP_CriticalSection, *tpBP_CriticalSection;

// Semaphore
typedef struct {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber)
  tpBP_TaskContext  pFirst;
  tpBP_TaskContext  pLast;
  uint16            Count;
} tBP_Semaphore, *tpBP_Semaphore;

// Callback function type definition for Module Init
typedef void (*tBP_InitFunc)(void);
typedef tBP_TaskId (*tBP_DispatchFunc)(tBP_SignalNo);

// Module Info
typedef struct tBP_ModuleInfo {
  uint16  MajorVersion;
  uint16  MinorVersion;
  char   *Description;
} tBP_ModuleInfo, *tpBP_ModuleInfo;

// Module Init Item to go in the init array
typedef struct tBP_ModuleInitItem {
  tBP_ModuleId    *pModuleId;
  tBP_InitFunc     InitFunc;
  char            *Name;
  tpBP_ModuleInfo  pInfo;
} tBP_ModuleInitItem, *tpBP_ModuleInitItem;

typedef struct tBP_MCBItem {
  tBP_DispatchFunc DispatchFunc;
} tBP_MCBItem;

// Event
typedef struct {
  BP_DECLARE_MAGIC_NUMBER(MagicNumber)
  tpBP_TaskContext  pTasks;
} tBP_Event, *tpBP_Event;



// Native OS Task IDs
#define BP_BTI      2
#define BP_BTU      3
#define BP_AT       4
#define ID_AMP      BP_BTI
#define ID_BTU      BP_BTU
#define ID_AT       BP_AT
#define ID_APPL     BP_AT



// Callback function type definitions
typedef void       (*tBP_ReceiveFunc)(tBP_Signal*);
typedef void       (*tBP_IdleFunc)(void);
typedef void       (*tBP_InterceptFunc)(tBP_Signal*);
typedef void       (*tBP_FatalFunc)(uint32 Reason, char *pFileName, uint16 LineNo);
typedef void       (*tBP_ShutdownFunc)(uint32 Reason);
typedef bool       (*tBP_BackgroundJobFunc)(uint32 Argument);

void BP_Send(tBP_ModuleId MID, tBP_Signal *pSignal);
void BP_SendToTask(tBP_TaskId TId,tBP_Signal *pSignal);
void BP_IsrSend(tBP_ModuleId MId, tBP_Signal *pSignal);
void BP_IsrSendToTask(tBP_TaskId TId,tBP_Signal *pSignal);
tBP_Signal* BP_AllocSignal(tBP_SignalNo SignalNo, tBP_DataSize DataSize);
tBP_Signal* BP_IsrAllocSignal(tBP_SignalNo SignalNo, tBP_DataSize DataSize);
void BP_ReleaseSignal(tBP_Signal *pSignal);
void BP_IsrReleaseSignal(tBP_Signal *pSignal);
void* BP_AllocMemory(tBP_DataSize DataSize);
void BP_ReleaseMemory(void* pMemory);
void BP_RequestSystemShutdown(uint32 Reason);
void BP_ReportTaskShutdownDone(void);
void BP_SystemFatal(uint32 Reason,char *pFileName, uint16 LineNo);
bool BP_IsIsrMode(void);
uint8* BP_ReserveMemory(uint32 Size);
uint8* BP_ReservePoolMemory(uint32 NoOfBlocks, uint32 BlockSize);
tpBP_MemPool BP_CreatePool(char *Name, uint8 *pMem, uint32 NoOfBlocks,
                          uint32 BlockSize, tBP_PoolNotifyFunc PoolNotifyFunc);
void BP_ResetPool(tpBP_Pool pPool);
void* BP_GetFromPool(tpBP_MemPool pMemPool);
void BP_ReturnToPool(void *p);
tpBP_Heap BP_CreateHeap(char *Name, char *pMem, uint32 MemSize,
                        uint16 *pSizeTable);
void* BP_GetFromHeap(tpBP_Heap pHeap, uint32 Size);
void BP_ReturnToHeap(tpBP_Heap pHeap, void *p);
void BP_PurgeHeap(tpBP_Heap pHeap);
void BP_PurgeAllHeaps(void);
bool BP_ReturnToAnyHeap(void *p);
bool BP_TryReturnToHeap(void *p);
void BP_ReturnToHeapLater(void *p);
tBP_TaskId BP_GetOwnerOfHeapBlock(void *p);
void BP_TakeOwnershipOfHeapBlock(void *p);
void BP_Release(void *p);
void BP_InitQueue(tBP_Queue *pQueue);
void BP_SetQueueLimit(tBP_Queue *pQueue, uint16 Limit);
void BP_Queue(tBP_Queue *pQueue, void *pMem);
void BP_QueueInFront(tBP_Queue *pQueue, void *pMem);
void* BP_GetFromQueue(tBP_Queue *pQueue);
uint32 BP_GetShutdownReason(void);


// Alias to OS
#define OS_ReleaseSignal        BP_ReleaseSignal
#define OS_IsrReleaseSignal     BP_IsrReleaseSignal
#define OS_Release              BP_Release


#endif //BACKPLANE_H

