/*---------------------------------------------------------------------------*
  Project:  NitroSDK - OS - demos - waitIrq-2
  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.3  2004/08/06 12:45:46  yada
  change key interrupt logic enum

  Revision 1.2  2004/08/06 05:14:04  yada
  PAD_SetIrq -> PADi_SetIrq, PAD_ClearIrq -> PADi_ClearIrq

  Revision 1.1  2004/05/20 00:54:45  yada
  initial release

  Revision 1.2  2004/04/30 05:02:25  yada
  add comment

  Revision 1.1  2004/04/30 04:37:56  yada
  first release

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

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

#define    STACK_SIZE     1024
#define    THREAD1_PRIO   17
#define    THREAD2_PRIO   18
OSThread   thread1;
OSThread   thread2;
u32        stack1[ STACK_SIZE/sizeof(u32) ];
u32        stack2[ STACK_SIZE/sizeof(u32) ];

/* ----------------
 * Enable either one of define below and verify the difference of operation.  
 *         */

#define WAIT_KEY
//#define WAIT_ANY

/*  thread1 and thread2 stop waiting for IRQ.
 *  If WAIT_KEY is enabled, only thread1 will run.
 *  If WAIT_ANY is enabled, both thread1 and thread2 will run.
 *  This is because in case of WAIT_KEY, thread1 enters OS_WaitIrq() again after clearing interrupt check flag after returning from OS_WaitIrq() by key interrupt.  
 *   
 *  proc2 becomes operable once, but cannot exit from OS_WaitIrq() because key interrupt check flag is already cleared.
 *   
 *
 *  In case of WAIT_ANY, the moment interrupt occurs, thread1 and thread2 become executable.
 *   So, when thread1 comes for the next OS_WaitAnyIrq(),
 *  thread2 can run.
 */

// Check if either one was enabled
#if (defined(WAIT_KEY) && defined(WAIT_ANY)) || (!defined(WAIT_KEY) && !defined(WAIT_ANY))
***** ERROR. define either from WAIT_KEY or WAIT_ANY.
#endif

//================================================================================
/*---------------------------------------------------------------------------*
  Name:         NitroMain

  Description:  main

  Arguments:    None

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

    //---- key interrupt setting
    (void)OS_SetIrqFunction( OS_IE_KEY, KeyIntr );
    (void)OS_EnableIrqMask( OS_IE_KEY );
    (void)OS_EnableIrq();
    PADi_SetIrq( PAD_LOGIC_OR, TRUE, PAD_KEYPORT_MASK );

    //---- create and wakeup threads
    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 );

    OS_Printf( "please push any button.\n" );

    //---- idle loop
    while(1)
    {
       OS_SleepThread(NULL);
       // never wake up
    }

    // never reach
}

//--------------------------------------------------------------------------------
//    Key interrupt handler
//
void KeyIntr( void )
{
    OS_SetIrqCheckFlag( OS_IE_KEY );
}

//--------------------------------------------------------------------------------
//    proc1
//
void  proc1( void* )
{
    int n=0;

    while(1)
    {
      OS_Printf( "thread 1\n" );
#ifdef WAIT_KEY
      OS_WaitIrq( TRUE, OS_IE_KEY );
#endif
#ifdef WAIT_ANY
      OS_WaitAnyIrq();
#endif
    }
}

//--------------------------------------------------------------------------------
//    proc2
//
void  proc2( void* )
{
    int n=0;
    while(1)
    {
      OS_Printf( "thread 2\n" );
#ifdef WAIT_KEY
      OS_WaitIrq( TRUE, OS_IE_KEY );
#endif
#ifdef WAIT_ANY
      OS_WaitAnyIrq();
#endif
    }
}


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