/*******************************************************************************
* Project:      Amped'RF Bluetooth
* File name:    GKI_FreeRTOS.h
* Description:  OS abstraction header for FreeRTOS.
*
* Note: Modules are defined as a task with an associated msg queue
*
* Copyright (c) 2012 Amped'RF Inc., AR Technology  All rights reserved.
*******************************************************************************/
#ifndef _GKI_FREERTOS_H_
#define _GKI_FREERTOS_H_
#ifdef FREE_RTOS

#include "Custom.h"
#include "Config.h"
#include "TM_Device.h"
#include "Signals.h"


#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#define SDC_ZERIAL_INTERFACE        true
#define SDC_HCI_INTERFACE           false

#define GPIO_IN_TRI_CMOS            GPIO_Mode_IN_FLOATING   // INPUT TRSISTATE CMOS
#define GPIO_IPUPD_WP               GPIO_Mode_IN_FLOATING   // INPUT PULL UP/PULL DOWN WEAK PUSH PULL
#define GPIO_OUT_PP                 GPIO_Mode_Out_PP        // OUTPUT PUSH PULL
#define GPIO_AF_PP                  GPIO_Mode_AF_PP         // ALTERNATE FUNCTION PUSH PULL
#define UART_TypeDef                USART_TypeDef

#define UART_OnOffConfig(x,y)
#define UART_BaudRateConfig(x, y)   TM_SetBaudrate(x, y)


//-----------------------------------------------------
//        Defines
//-----------------------------------------------------
#define MIN_SIGNAL_SIZE             64
#define GKI_INVALID_PTR             ((void *)&GKI_Data.InvalidPointer)
#define GKI_INVALID_TID             0xFFFF
#define GKI_INVALID_MID             0xFFFF
#define GKI_INVALID_PRIO            0xFFFF
#define GKI_INVALID_SIGNAL_NUMBER   0xFFFF
#define MS(x)                       ( x / portTICK_RATE_MS )

#define GKI_NO_OF_SHORT_SIGNALS     40
#define GKI_NO_OF_LONG_SIGNALS      10
#define GKI_SHORT_SIGNAL_SIZE       80  // In Bytes
#define GKI_LONG_SIGNAL_SIZE        370 // In Bytes

#define RAM_VALID(m)                GKI_MemoryValid(m)
#define ASSERT_VALID_RAM(m,s)       fatalc(GKI_MemoryValid(m),s)

#define GKI_ENTER_CRITICAL_SECTION(CS)  CS = GKI_enter_critical()
#define GKI_EXIT_CRITICAL_SECTION(CS)   GKI_set_interrupt_state(CS)
#define GKI_ASSERT(cond, comment)       assertc(cond, comment)
#define GKI_ASSERT_VALID_PTR(Ptr)       GKI_ASSERT(((Ptr) != GKI_INVALID_PTR),"BadPtr")
#define GKI_FATAL(comment)              fatalc(0, comment)

#define NORMAL_PRIORITY                 (tskIDLE_PRIORITY+3)
#define VERY_LOW_PRIORITY               (NORMAL_PRIORITY-2)
#define LOW_PRIORITY                    (NORMAL_PRIORITY-1)
#define HIGH_PRIORITY                   (NORMAL_PRIORITY+1)
#define VERY_HIGH_PRIORITY              (NORMAL_PRIORITY+2)



//-----------------------------------------------------
//     Memory pool defines
//-----------------------------------------------------
enum {
    GKI_POOL_ID_0=0,
    GKI_POOL_ID_1,
    GKI_POOL_ID_2,
    GKI_POOL_ID_3,
    GKI_POOL_ID_4,
    GKI_BUF_POOL_NUM
};
#define GKI_BUF0_MAX            12
#define GKI_BUF1_MAX            4
#define GKI_BUF2_MAX            2
#define GKI_BUF3_MAX            3
#define GKI_BUF4_MAX            1
#define GKI_BUF0_SIZE           64
#define GKI_BUF1_SIZE           256
#define GKI_BUF2_SIZE           384
#define GKI_BUF3_SIZE           660
#define GKI_BUF4_SIZE           1500




//-----------------------------------------------------
//     Typedefs and Structures
//-----------------------------------------------------
typedef u16 tGKI_TaskId;
typedef u16 tGKI_ModuleId;
typedef u16 tGKI_DataSize;
typedef u32 tGKI_SignalNo;
typedef u32 tGKI_Critical;
typedef u32 tGKI_Result;
typedef void * tGKI_SEM_ID;
typedef u32 tCriticalSection;


//-----------------------------------------------------
//     Uart interrupt source
//-----------------------------------------------------
#define GKI_IntSrc_IDLE     0   // Idle char timeout
#define GKI_IntSrc_FULL     1   //
#define GKI_IntSrc_HALF     2
#define GKI_IntSrc_SWI      3
#define GKI_IntSrc_RXNE     4
#define GKI_IntSrc_ERR      5




// Signal Header
typedef struct tGKI_SignalHead {
    tGKI_SignalNo       SignalNumber;
    tGKI_ModuleId       SenderTaskId;
    tGKI_ModuleId       OwnerTaskId;
    tGKI_DataSize       DataSize;
    struct tGKI_Signal *pNextSignal;
} tGKI_SignalHead;


// Signal Data
typedef union tGKI_SignalData
{
    u8  Byte[MIN_SIGNAL_SIZE];
    BP_CoreSignalUnionStructure;
    BP_BTISignalUnionStructure;
} tGKI_SignalData;


// Signal Structure
typedef struct tGKI_Signal {
    tGKI_SignalHead Head;
    tGKI_SignalData Data;
} tGKI_Signal, *tpGKI_Signal;


// Memory Block Head
typedef struct tGKI_MemBlock {
    struct tGKI_Pool     *pOwnerPool;
    struct tGKI_MemBlock *pNext;
    struct tGKI_MemBlock *pMemHeader;
} tGKI_MemBlock, *tpGKI_MemBlock;


// Queue Structure
typedef struct GKI_BUFFER_Q {
    tpGKI_MemBlock p_first;
    tpGKI_MemBlock p_last;
    u16        count;
    u16        limit;
} GKI_BUFFER_Q, tGKI_Queue, *tpGKI_Queue;


// Typedef Functions
typedef void    (*tGKI_InitFunc)(void);
typedef void    (*tGKI_ReceiveFunc)(tGKI_Signal*);
typedef void    (*tGKI_IdleFunc)(void);
typedef void    (*tGKI_InterceptFunc)(tGKI_Signal*);
typedef void    (*tGKI_FatalFunc)(uint32 Reason, char *pFileName, uint16 LineNo);
typedef void    (*tGKI_ShutdownFunc)(uint32 Reason);
typedef void    (*tGKI_PoolNotifyFunc)(struct tGKI_Pool*);
typedef void    (*tGKI_Task)(void *);



// Memory Pool
typedef struct tGKI_Pool {
    char                *Name;
    u32                  NoOfBlocks;
    u32                  BlockSize;
    u32                  BlockUse;
    u32                  BlockUsePeak;
    void *               TopAddress;
    tGKI_PoolNotifyFunc  NotifyFunc;
    struct tGKI_Pool    *pNextPool;
    tpGKI_MemBlock       pFreeBlock;
} tGKI_Pool, *tpGKI_Pool, tGKI_MemPool, *tpGKI_MemPool;


// Major GKI states
typedef enum tGKI_State {
    eGKI_State_ModuleInit=0,
    eGKI_State_TaskInit,
    eGKI_State_Running,
    eGKI_State_Shutdown
} tGKI_State;



// Short Signal
typedef struct tGKI_ShortSignal {
    tGKI_SignalHead Head;
    uint8          Byte[GKI_SHORT_SIGNAL_SIZE];
} tGKI_ShortSignal;


// Long Signal
typedef struct tGKI_LongSignal {
    tGKI_SignalHead Head;
    uint8          Byte[GKI_LONG_SIGNAL_SIZE];
} tGKI_LongSignal;


//-------------------------------
//  Local data for GKI
//-------------------------------
typedef struct tGKI_Data {
    tGKI_State          State;
    u32                 ReadyFlags;
    uint8               InvalidPointer;
    tGKI_FatalFunc      FatalFunc;
    tGKI_Pool          *MemPoolList;
    uint8               ShutdownRequested;
    uint32              ShutdownReason;
    tGKI_TaskId         ExecutingTaskId;
    tGKI_TaskId         KernelExecTaskId;
    tGKI_TaskId         TaskPrioList;
    tGKI_TaskId         SignalPendingTId;
    tGKI_Signal        *FreeShortSignalList;
    tGKI_Signal        *FreeLongSignalList;
    tGKI_ShortSignal    ShortSignals[GKI_NO_OF_SHORT_SIGNALS];
    tGKI_LongSignal     LongSignals[GKI_NO_OF_LONG_SIGNALS];
    u32                 TotalStackSize;
    u32                 TotalQueueSize;
    u32                 TotalPoolSize;
} tGKI_Data;


//-------------------------------
//    GLOBALS
//-------------------------------
extern tGKI_Data GKI_Data;
extern u32 TM_TICKS_PER_SECOND;
extern u32 TM_TICKS_PER_MILLISECOND;



// Module Info
typedef struct tGKI_ModuleInfo {
  uint16  MajorVersion;
  uint16  MinorVersion;
  char   *Description;
} tGKI_ModuleInfo, *tpGKI_ModuleInfo;


// General buffer pools
typedef struct {
    char *  Name;
    uint16  Num;
    uint16  Size;
    tGKI_PoolNotifyFunc NotifyFunction;
} tGKI_BufPool;



//-----------------------------------------------------------------
// Structure to handle module definitions for FreeRTOS
//-----------------------------------------------------------------
typedef struct {
    char Name[configMAX_TASK_NAME_LEN];
    xTaskHandle TaskHandle;
    xQueueHandle QueueHandle;
    u32 StackSize;
    bool Initialized;
} tGKI_Module;
extern tGKI_Module GKI_Module[];


//-----------------------------------------------------------------
// Task definitions for FreeRTOS
//-----------------------------------------------------------------
void SYS_Task(void *pvParameters);
void TM_Task(void *pvParameters);
void AMP_Task(void *pvParameters);
void BTU_Task(void *pvParameters);
void AT_Task(void *pvParameters);
void APPL_Task(void *pvParameters);


//-----------------------------------------------------------------
//    Module IDs
//-----------------------------------------------------------------
enum {
    ID_SYS = 0,
    ID_TM,
    ID_AMP,
    ID_BTU,
    ID_AT,
    ID_APPL,
    MAX_MODULES
};
#define ID_BTI          ID_AMP
#define GKI_KERNEL_TID  ID_SYS


//-------------------------------------
// Task Ready Flags
//-------------------------------------
#define GKI_READY_POOLS     0x0001
#define GKI_READY_TM        0x0002
#define GKI_READY_AMP       0x0004
#define GKI_READY_BTU       0x0008
#define GKI_READY_AT        0x0010
#define GKI_READY_APPL      0x0020




//-----------------------------------------------------------------
// Define Legacy types as GKI types
//-----------------------------------------------------------------
#define BP_KERNEL_TID               ID_SYS
#define BP_TM                       ID_TM
#define BP_BTI                      ID_AMP
#define BP_BTU                      ID_BTU
#define BP_AT                       ID_AT
#define BP_APP                      ID_APPL
#define tBP_TaskId                  tGKI_TaskId
#define tBP_TaskPrio                tGKI_TaskPrio
#define tBP_DataSize                tGKI_DataSize
#define tBP_SignalNo                tGKI_SignalNo
#define tOS_SignalNo                tGKI_SignalNo
#define tBP_TaskName                tGKI_TaskName
#define tBP_ModuleId                tGKI_ModuleId
#define tBP_Critical                tGKI_Critical
#define tBP_PoolNotifyFunc          tGKI_PoolNotifyFunc
#define tBP_SignalHead              tGKI_SignalHead
#define tBP_SignalData              tGKI_SignalData
#define tBP_Signal                  tGKI_Signal
#define tpBP_Signal                 tpGKI_Signal
#define tBP_MemBlock                tGKI_MemBlock
#define tpBP_MemBlock               tpGKI_MemBlock
#define BUFFER_Q                    GKI_BUFFER_Q
#define tBP_Pool                    tGKI_Pool
#define tpBP_Pool                   tpGKI_Pool
#define tBP_MemPool                 tGKI_MemPool
#define tpBP_MemPool                tpGKI_MemPool
#define BP_AllocMemory              GKI_AllocMemory
#define BP_ReleaseMemory            GKI_ReleaseMemory
#define BP_GetFromPool              GKI_GetFromPool
#define BP_ReturnToPool             GKI_ReturnToPool
#define BP_InitQueue                GKI_InitQueue
#define BP_AllocSignal              GKI_AllocSignal
#define BP_Send                     GKI_Send
#define BP_IsrAllocSignal           GKI_IsrAllocSignal
#define BP_IsrSend                  GKI_IsrSend
#define BP_ReleaseSignal            GKI_ReleaseSignal
#define BP_TimerRegisterRequest     GKI_TimerRegisterRequest
#define BP_TimerCancel              GKI_TimerCancel
#define tBP_Queue                   tGKI_Queue
#define tpBP_Queue                  tpGKI_Queue
#define BP_GetSignalNo              GKI_GetSignalNo
#define BP_GetSignalDataPtr         GKI_GetSignalDataPtr
#define BP_ResetPool                GKI_ResetPool
#define BP_Release                  GKI_ReleaseSignal
#define BP_IS_ISR_MODE              GKI_IS_ISR_MODE
#define BP_ASSERT_ISR_MODE          GKI_ASSERT_ISR_MODE
#define BP_ASSERT_USER_MODE         GKI_ASSERT_USER_MODE
#define BP_DEFAULT_PRIO             (tskIDLE_PRIORITY+3)
#define BP_ReportTaskShutdownDone   GKI_ReportTaskShutdownDone
#define BP_RequestSystemShutdown    GKI_RequestSystemShutdown
#define BP_SendToTask               GKI_Send
#define tBP_ModuleInfo              tGKI_ModuleInfo
#define tpBP_ModuleInfo             tpGKI_ModuleInfo
#define BP_Data                     GKI_Data
#define BP_INVALID_TID              GKI_INVALID_TID
#define BP_TakeOwnershipOfSignal    GKI_TakeOwnershipOfSignal
#define BP_ASSERT_SIG_NUMBER        GKI_ASSERT_SIG_NUMBER
#define BP_ASSERT_INVALID_PTR       GKI_ASSERT_INVALID_PTR
#define BP_INVALID_TID              GKI_INVALID_TID
#define BP_INVALID_MID              GKI_INVALID_MID
#define BP_INVALID_PRIO             GKI_INVALID_PRIO
#define BP_INVALID_SIGNAL_NUMBER    GKI_INVALID_SIGNAL_NUMBER
#define BP_GetSignalSender          GKI_GetSignalSender
#define BP_ReserveMemory            GKI_AllocMemory
#define BP_GetExecutingTaskId       GKI_GetExecutingTaskId
#define BP_IsrFindTask(Task,Sig)    Task
#define BP_GetCurrentModule         GKI_GetCurrentModuleId
#define BP_IsrSendToTask            GKI_IsrSend


//-----------------------------------------------------------------
//  GKI implementation
//-----------------------------------------------------------------
#define GKI_GetSignalNo(pSig)       ((pSig)->Head.SignalNumber)
#define GKI_GetSignalDataPtr(pSig)  (&((pSig)->Data.Byte[0]))
#define GKI_ASSERT_ISR_MODE()       assertc((GKI_IS_ISR_MODE()), "NotISRmode")
#define GKI_ASSERT_USER_MODE()      assertc((!GKI_IS_ISR_MODE()),"NotUserMode")
#define GKI_ASSERT_SIG_NUMBER(No)   assertc(((No) != GKI_INVALID_SIGNAL_NUMBER),"BadSigNo")
#define GKI_ASSERT_INVALID_PTR(Ptr) assertc(((Ptr) == GKI_INVALID_PTR),"BadPtr")
#define BP_SaveSignal(pSignal)          // Check
#define GKI_GetSignalSender(pSig)   pSig->Head.SenderTaskId
#define GKI_WaitUntilState(x)       while (GKI_Data.State != x) {GKI_WaitMS(5);}
#define GKI_SetState(x)             GKI_Data.State = x
#define GKI_GetState()              GKI_Data.State
#define GKI_ModuleName()            GKI_Module[ GKI_GetExecutingTaskId() ].Name
#define GKI_YieldFromISR()          vPortYieldFromISR()


//-----------------------------------------------------------------------
// FreeRTOS GKI Function defines
//-----------------------------------------------------------------------
bool GKI_CreateModule(u16 id, tGKI_Task pvTaskCode,
                           const char * pcName,
                           u16 queueSize,
                           u16 usStackDepth,
                           u16 uxPriority);
tpGKI_Pool      GKI_CreatePool(const char *name, u16 num, u16 size, tGKI_PoolNotifyFunc NotifyFunc);
void           *GKI_GetFromPool(tpGKI_Pool pPool);
void            GKI_ReturnToPool (void *memblock);
tGKI_Signal    *GKI_AllocSignal(tGKI_SignalNo SignalNo, tGKI_DataSize DataSize);
tGKI_Signal    *GKI_IsrAllocSignal(tGKI_SignalNo SignalNo, tGKI_DataSize DataSize);
void            GKI_ReportTaskShutdownDone(void);
void            GKI_RequestSystemShutdown(uint32 Reason);
tGKI_Signal    *GKI_Receive(void);
void            GKI_ResetPool(tpGKI_Pool pPool);
void            GKI_RequestSystemShutdown(uint32 Reason);
void            GKI_ReportTaskShutdownDone(void);
void            GKI_TakeOwnershipOfSignal(tGKI_Signal *pSignal);
tGKI_TaskId     GKI_GetExecutingTaskId(void);
tGKI_TaskId     GKI_GetCurrentModuleId(void);
void           *GKI_getfirst(GKI_BUFFER_Q *p_q);
void           *GKI_remove_from_queue(GKI_BUFFER_Q *p_q, void *p_buf);
uint8          *GKI_ReserveMemory(char *name, uint32 size);
void            GKI_Start(void);
void            GKI_Send(tGKI_ModuleId id, tGKI_Signal *pSignal);
void            GKI_IsrSend(tGKI_ModuleId id, tGKI_Signal *pSignal);
void            GKI_WaitMS(u32 x);
bool            GKI_DeviceUp(void);
void            GKI_InitSignals(void);
void            GKI_ReleaseSignal(tGKI_Signal *pSignal);
void            GKI_SystemFatal(uint32 Reason, char *pFileName, uint16 LineNo);
void           *GKI_AllocMemory(size_t sz);
void            GKI_ReleaseMemory(void *mem);
void            GKI_EndTask(void);
tGKI_Critical   GKI_enter_critical(void);
void            GKI_exit_critical(tGKI_Critical cs);
void            GKI_GenerateSystemReset(void);
bool            GKI_IS_ISR_MODE(void);
void            GKI_disable_interrupt(void);
void            GKI_enable_interrupt(void);
tGKI_Critical   GKI_get_interrupt_state(void);
void            GKI_set_interrupt_state(tGKI_Critical cs);
u32             GKI_get_tick_count(void);
void            GKI_set_tick_timeout(u32 ticks);
void            GKI_putstring(char *msg);
char *          GKI_GetModuleNameFromId(u16 id);
void            GKI_WaitUntilReady(u32 x);
void            GKI_SetReady(u32 x);
bool            GKI_MemoryValid(void *);

// Callbacks
void            UART_RxHandler(u16 u, u16 iSrc);
void            UART_TxCompleteHandler(u16 u);
void            TM_TimeoutIsr(void);

// IO routines
void  IO_BitWrite(u16 io, u8 BitVal);
void  IO_WriteBit(u16 io, u8 BitVal);
void  IO_Init(u16 io, u8 mode);
void  IO_Config(u16 io, u8 mode);
uint8 IO_BitRead(u16 io);
void  UART_SetBaudrate(u16 u, u32 baudrate);


#ifdef STACK_ONLY
#define USART1           ((void *)0x0000)
#define USART2           ((void *)0x0001)
#define EXTI_Line0       ((u32)0x00001)  /* External interrupt line 0 */
#define EXTI_Line1       ((u32)0x00002)  /* External interrupt line 1 */
#define EXTI_Line2       ((u32)0x00004)  /* External interrupt line 2 */
#define EXTI_Line3       ((u32)0x00008)  /* External interrupt line 3 */
#define EXTI_Line4       ((u32)0x00010)  /* External interrupt line 4 */
#define EXTI_Line5       ((u32)0x00020)  /* External interrupt line 5 */
#define EXTI_Line6       ((u32)0x00040)  /* External interrupt line 6 */
#define EXTI_Line7       ((u32)0x00080)  /* External interrupt line 7 */
#define EXTI_Line8       ((u32)0x00100)  /* External interrupt line 8 */
#define EXTI_Line9       ((u32)0x00200)  /* External interrupt line 9 */
#define EXTI_Line10      ((u32)0x00400)  /* External interrupt line 10 */
#define EXTI_Line11      ((u32)0x00800)  /* External interrupt line 11 */
#define EXTI_Line12      ((u32)0x01000)  /* External interrupt line 12 */
#define EXTI_Line13      ((u32)0x02000)  /* External interrupt line 13 */
#define EXTI_Line14      ((u32)0x04000)  /* External interrupt line 14 */
#define EXTI_Line15      ((u32)0x08000)  /* External interrupt line 15 */
#define EXTI_Line16      ((u32)0x10000)  /* External interrupt line 16 */
#define USART_Parity_No                      ((u16)0x0000)
#define USART_Parity_Even                    ((u16)0x0400)
#define USART_Parity_Odd                     ((u16)0x0600)
#define USART_HardwareFlowControl_None       ((u16)0x0000)
#define USART_HardwareFlowControl_RTS        ((u16)0x0100)
#define USART_HardwareFlowControl_CTS        ((u16)0x0200)
#define USART_HardwareFlowControl_RTS_CTS    ((u16)0x0300)
#define EXTI0_IRQChannel             ((u8)0x06)  /* EXTI Line0 Interrupt */
#define EXTI1_IRQChannel             ((u8)0x07)  /* EXTI Line1 Interrupt */
#define EXTI2_IRQChannel             ((u8)0x08)  /* EXTI Line2 Interrupt */
#define EXTI3_IRQChannel             ((u8)0x09)  /* EXTI Line3 Interrupt */
#define EXTI4_IRQChannel             ((u8)0x0A)  /* EXTI Line4 Interrupt */
typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;

typedef void * GPIO_TypeDef;
typedef void * USART_TypeDef;
typedef void * DMA_Channel_TypeDef;

#endif // STACK_ONLY

#ifdef STACK_ONLY
bool  TM_HciReadyToSend(void);
void  TM_MainUartReceiveEnable(bool enb);
void  TM_BTControllerWake(void);
void  TM_BTControllerSleep(void);
void  TM_IsUartRxNotEmpty(void *Uart);
void  TM_IsUartTxEmpty(void *Uart);
void  TM_HciReceiveEnable(bool enb);
void  TM_IsUartTxFull(void *Uart);
void  TM_IsUartTxHalfEmpty(void *Uart);
void  TM_IsUartRxTOIdle(void *Uart);
void  TM_SetUartChrTimeout(void *Uart, u16 timeout);
void  TM_EnableMainUartTxInterrupt(void);
void  TM_DisableMainUartTxInterrupt(void);
bool  TM_GetHostWake(void);
#endif

void  TM_SetPioAsOutput(u16 Pin);
void  TM_SetPioAsInput(u16 Pin);
void  TM_ResetPio(u16 Pin);
bool  TM_ReadPio(u16 Pin);
void  TM_SetPio(u16 Pin);


//-----------------------------------------------------------------------
// Compiler intrinsics
//-----------------------------------------------------------------------
#ifndef __IAR_SYSTEMS_LIB__
const char *__iar_Strchr(const char *_S, int _C);
const char *__iar_Strstr(const char *s1, const char *s2);
unsigned long __iar_Stoul(const char *_S, char **_Endptr, int _Base);
#endif



#endif // FREE_RTOS
#endif // _GKI_FREERTOS_H_
