// Copyright (c) 2004 Rowley Associates Limited.
//
// This file may be distributed under the terms of the License Agreement
// provided with this software.
//
// THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

// Test message queues and memory blocks

#include <ctl_api.h>

CTL_TASK_t main_task, new_task; // task blocks

CTL_MESSAGE_QUEUE_t mq;
#define QSIZE 10
void *queue[QSIZE]; // the message queue of pointers

CTL_MEMORY_AREA_t ma;
#define MSIZE 20
unsigned memory[20]; // the memory area in words

#define CALLSTACKSIZE 16 // this is only required for AVR builds
#define STACKSIZE 64          
unsigned new_task_stack[1+STACKSIZE+1];

void 
new_task_code(void *p)
{  
  int v=0;
  while (1)
    {             
      unsigned *m = ctl_memory_area_allocate(&ma);
      if (!m)
        ctl_handle_error(CTL_UNSPECIFIED_ERROR);
      *m = v;
      ctl_message_queue_post(&mq, m, 0, 0);
      v++;
    }  
}

void
ctl_handle_error(CTL_ERROR_CODE_t e)
{
  while (1);
}

int main(void)
{
 
  ctl_board_init();
  ctl_task_init(&main_task, 255, "main");
  ctl_start_timer(ctl_increment_tick_from_isr);
  ctl_message_queue_init(&mq, queue, QSIZE);
  ctl_memory_area_init(&ma, memory, 1, MSIZE);
  memset(new_task, 0xcd, sizeof(new_task));
  new_task_stack[0]=new_task_stack[1+STACKSIZE]=0xfacefeed;
  ctl_task_run(&new_task, 1, new_task_code, 0, "new_task", STACKSIZE, new_task_stack, CALLSTACKSIZE);  
  ctl_task_set_priority(&main_task, 0);
  while (1)
    {         
      int v;
      unsigned *m;
      if (!ctl_message_queue_receive(&mq, (void **)&m, 0, 0))
        ctl_handle_error(CTL_UNSPECIFIED_ERROR);
      v = *m;
      ctl_memory_area_free(&ma, m);
    }
  return 0;
}
