/*
 * os - real time os
 *
 * main.c - main setup.
 *
 * Perform initialization and provide null task.
 *
 * $Id: main.c,v 1.10 2002/08/02 20:05:07 tomdean Exp $
 *
 */
#include <sys/ports_def.h>  /* ports */
#include <sys/locks.h>      /* lock */
#include <os.h>             /* os declarations */
#include <lcd.h>            /* lcd buffers and functions */
#include <libeeprom.h>      /* eeprom functions */
#include <gps.h>

/*
 * rti() decrements tocks, and, when zero, does a context switch to
 * the next ready task in a round-robin fashion.
 * Normally, there are 4 ticks per tock.  This may be changed in os.h
 * by setting TICKS_PER_TOCK
 */
extern unsigned char tocks;

int main() {
  short idx;
  vector_t *vector = sci_sect_vector;
  register unsigned short loop_count = 0;

  /* trace */
  next_trace = (trace_t *)0x7500;
  *(unsigned short *)next_trace = 0x7502;

  /* initialize the lcd */
  display_init();

  /* initialize the gps task */
  gps_init();

  /* initialize the sci */
  sci_init();
 
  /* enable the rti interrupt */
  _io_ports[M6811_TMSK2] |= M6811_RTII;

  /* set data direction for port c */
  _io_ports[M6811_DDRC] = 0xff;  /* all outputs */

  /*
   * set ALL interrupt vectors to rti - just dismiss the interrupt.
   * later, add_handler() will redirect some.
   */
  while (vector <= clkfail_sect_vector){
	clear_handler(vector++, (task_t)0);
  }

  /*
   * connect context structures to the context array
   */
#define SET_CONTEXT(x) context_t context##x; context[ x ] = &context##x
  SET_CONTEXT(0);  /* filled when do the first context switch in null task */
  SET_CONTEXT(1);  /* filled in task_init */
  SET_CONTEXT(2);  /* filled in task_init */
  SET_CONTEXT(3);  /* filled in task_init */
  SET_CONTEXT(4);  /* filled in task_init */
  SET_CONTEXT(5);  /* filled in task_init */
  SET_CONTEXT(6);  /* filled in task_init */
  SET_CONTEXT(7);  /* filled in task_init */
  SET_CONTEXT(8);  /* filled in task_init */

  /*
   * initialize all 8 tasks
   * constructs a stack for context switching
   */
  task_init(1, task1,   stack1);
  task_init(2, task2,   stack2);
  task_init(3, adc,     adc_stack);
  task_init(4, gps,     gps_stack);
  task_init(5, task5,   stack5);
  task_init(6, cli,     cli_stack);
  task_init(7, task7,   stack7);
  task_init(8, display, display_stack);

  /*
   * set interrupt handlers for desired interrupts
   */
  add_handler(sci_sect_vector, (task_t)sci);
  add_handler(rti_sect_vector, (task_t)rti);
  add_handler(swi_sect_vector, (task_t)swi);

  /*
   * we are in main, and, main is the null task, as far as os is concerned,
   * once the first context switch happens
   */
  cur_task = 0;  /* null task */

  /*
   * initialize all task timers.
   */
  for (idx=1; idx<NUM_TASK+1; idx++) {
	timer[idx]=0;
	msg_queue[idx] = NULL;
  }

  /* setup context switching */
  tocks = TICKS_PER_TOCK;
  tick_count = 0;

  /* lcd buffers */
  lcd_row_1[40] = 0; /* null termination */
  lcd_row_2[40] = 0; /* null termination */
  lcd_row_3[40] = 0; /* null termination */
  lcd_row_4[40] = 0; /* null termination */
  error1[40]    = 0; /* null termination */
  error3[40]    = 0; /* null termination */
  error3_in_use = 0; /* switch the use of error3 */
  /*
   * gps message
   */

  /*
   * gps message variables
   */
  gps_init();
  
  /* allow interrupts */
  unlock();

  /*****************************************************
   * null task
   * we should run this some, if it never runs, we are cpu bound
   */
  while (1) {
	hex_to_ascii_4(++loop_count, TASK0_COUNT);	
  }
  /*****************************************************/

  /* we should NEVER get here */
  return 0;
}

/*
 * The default premain just clears the ccr
 * don't allow the default premain to allow interrupts
 * We want to do this later.
 */
void __premain() {
  return;
}

