/*************************************************************************** 
rtos_ex2							 
Applies Timer interrupt, clock tick, delays, and binary semaphore.
There are two tasks, of equal priority. One counts, the other displays the count. 

Salvo Lite RTOS, with Library sfc18sfa used. 
Can be simulated, or run on Derbot.
TJW 28.12.05
****************************************************************************/

#include <salvo.h>
#undef OSC	//necessary for this Salvo version, as it also defines this name
#include <p18f242.h>
#include <timers.h>

#pragma config OSC = HS, OSCS = OFF  //HS oscillator, oscillator switch off 
#pragma config PWRT = ON, BOR = OFF  //power-up timer on, brown-out detect off
#pragma config WDT = OFF		    //watchdog timer off
#pragma config STVR = ON, LVP = OFF  //Stack overflow reset enable on, 
						//low voltage programming off


#define BINSEM_Display OSECBP(1) 

//function prototypes. 
void Micro_Init(void);
//These functions are tasks.
void Count_Task( void );
void Display_Task( void );

//Define and initialise variable
unsigned char counter = 0;

//Define labels for context switches 
_OSLabel(Count_Task1)  
_OSLabel(Display_Task1)

/***************************************************************************
User-defined Functions, including RTOS Tasks.
****************************************************************************/
void Count_Task(void)
{
    for (;;) {				 //infinite loop
      counter++;
     OSSignalBinSem(BINSEM_Display);
  	OS_Delay (20,Count_Task1); //Task switch, and delay for 20x10ms, (200ms)
									//Use smaller delay for simulation 
   }
}

void Display_Task(void)
{
    for (;;) {				//infinite loop
     OS_WaitBinSem(BINSEM_Display, 100, Display_Task1);
     PORTC = counter<<5; 	     //Shift Counter left, and move to PORT C
     OS_Yield(Display_Task1);
    }
}
void Micro_Init(void)
{
//Initialise Port C
	TRISC = 0b10000000;
	PORTC = 0;		//Switch outputs off
/*Initialise TMR0: interrupt enabled,16-bit operation, internal clock, 
prescaler divide by 16, hence (with 4MHz clock) input cycle period of 16us*/
    OpenTimer0 (TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT & T0_PS_1_16);

	counter = 0;
}

/***************************************************************************
Main
****************************************************************************/
void main( void )
{	
//Initialise Microcontroller
	Micro_Init();
//Initialise RTOS
    OSInit();
    OSCreateTask(Count_Task, OSTCBP(1), 10);  //Create the Count_Task Task
    OSCreateTask(Display_Task, OSTCBP(2), 10); //Create the Display_Task Task
    OSCreateBinSem(BINSEM_Display, 0);	//Create the Binary Semaphore
//Enable interrupts
    OSEi(); 		
//Scheduling Loop
    for (;;)
        OSSched();
}

