/*---------------------------------------------------------------------------*
  Project:  NitroSDK - OS - demos - thread-4
  File:     main.c

  Copyright 2003,2004 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Log: main.c,v $
  Revision 1.10  2004/04/15 06:51:12  yada
  arranged comment

  Revision 1.9  2004/03/08 08:31:58  yada
  fixed top comment

  Revision 1.8  2004/02/26 05:51:46  yada
  modified due to the addition of argument for start function to OS_CreateThread().

  Revision 1.7  2004/02/24 00:05:20  yada
  (none)

  Revision 1.6  2004/02/05 07:09:03  yasu
  changed SDK prefix iris -> nitro

  Revision 1.5  2004/02/02 05:34:12  yada
  OS_SetIrqMask() -> OS_EnableIrqMask()

  Revision 1.4  2004/01/18 06:49:20  yada
  (none)

  Revision 1.3  2004/01/09 10:53:49  yada
  rewrote set function for interrupt check flag

  Revision 1.2  2003/12/25 07:32:21  yada
  chenged by integration of type rule

  Revision 1.1  2003/12/16 06:30:36  yasu
  sample of thread switch processing by thread-4 interrupt

  $NoKeywords: $
 *---------------------------------------------------------------------------*/
#include <nitro.h>

void       VBlankIntr(void);

#define    STACK_SIZE     1024
#define    THREAD1_PRIO   1
#define    THREAD2_PRIO   2

void       proc1( void* );
void       proc2( void* );

OSThread  thread1;
OSThread  thread2;

u32        stack1[ STACK_SIZE/sizeof(u32) ];
u32        stack2[ STACK_SIZE/sizeof(u32) ];

//================================================================================
//      Sample of thread switch using interrupt
//      Can make thread sleep/wake up in IRQ handler. However, actual thread
//      switching is postponed until IRQ routine ends.
/*---------------------------------------------------------------------------*
  Name:         NitroMain

  Description:  main

  Arguments:    None

  Returns:      None
 *---------------------------------------------------------------------------*/
void NitroMain()
{
    s32   n;

    OS_Init();

    //================ Start thread
    OS_InitThread();
    OS_CreateThread( &thread1, proc1, NULL, stack1 + STACK_SIZE/sizeof(u32), STACK_SIZE, THREAD1_PRIO );
    OS_CreateThread( &thread2, proc2, NULL, stack2 + STACK_SIZE/sizeof(u32), STACK_SIZE, THREAD2_PRIO );
    OS_WakeupThreadDirect( &thread1 );
    OS_WakeupThreadDirect( &thread2 );

    //================ Setting
#ifdef SDK_ARM9
    //---- Initialize graphics
    GX_Init();
#endif // SDK_ARM9

    //----  Enable Vblank interrupt
    (void)OS_SetIrqFunction( OS_IE_V_BLANK, VBlankIntr );
    (void)OS_EnableIrqMask( OS_IE_V_BLANK );
    (void)OS_EnableIrq();

    //---- V-Blank occurrence setting
    (void)GX_VBlankIntr( TRUE );

    //================ Main loop
    for ( n = 0; n < 5; n ++ )
    {
        //---- Wait for V-Blank interupt ends
        SVC_WaitVBlankIntr();

        OS_Printf( "Idle\n" );
    }

    OS_Printf( "==== Finish sample.\n" );
    OS_Terminate();
}

//--------------------------------------------------------------------------------
//     V-Blank interrupt processing(processing in IRQ)
//
void VBlankIntr(void)
{
    //---- Interrupt check flag
    OS_SetIrqCheckFlag( OS_IE_V_BLANK );
    
    //---- Start thread 1
    OS_WakeupThreadDirect( &thread1 );
}

//--------------------------------------------------------------------------------
//    proc1
//
void  proc1( void* )
{
    while (1)
    {
        OS_Printf( "------- Thread1 sleep\n" );
        OS_SleepThread( NULL );
        OS_Printf( "------- Thread1 wakeup\n" );
        
        //---- Start thread 2
        OS_WakeupThreadDirect( &thread2 );
    }
}

//--------------------------------------------------------------------------------
//    proc2
//
void  proc2( void* )
{
    while (1)
    {
        OS_Printf( "--------------- Thread2 sleep\n" );
        OS_SleepThread( NULL );
        OS_Printf( "--------------- Thread2 wakeup\n" );
    }
}

/*====== End of main.c ======*/
