/*
 * This file and its contents are supplied under the terms of the
 * Mozilla Public License (MPL) version 2.0.  You may only use this
 * file in accordance with the terms of version 2.0 of the MPL.
 *
 * A full copy of the text of the MPL should have accompanied this
 * source.  A copy of the MPL is also available via the Internet at
 * https://www.mozilla.org/en-CA/MPL/2.0.
 *
 * This Source Code Form is "Incompatible With Secondary Licenses",
 * as defined by the Mozilla Public License, v. 2.0.
 *
 * This file implements a program to demonstrate Concurrent C.
 * Not all of the advanced features are used here.
 *
 * (C) Copyright Rich Teer 1990, 2023, 2026.
 */


#include "proc.h"
#include "pit.h"

static pit_t *pit = (pit_t *)0x800000;
int taska_id;													/* Declare task A's ID */
int taskb_id;													/* Declare task B's ID */
int taskc_id;													/* Declare task C's ID */
int temperature;												/* The temperature */
int new_stack[4096];											/* Declare a BIG stack */
int *stack = &new_stack[4095];									/* Give us a pointer to its base */


int main (void)
{
	big_stack ();												/* Start using the big stack */
	scheduler ();												/* Call the scheduler */
}


void scheduler (void)
{
	void (taska *)(void);										/* Declare task A */
	void (taskb *)(void);										/* Declare task B */
	void (taskc *)(void);										/* Declare task C */
	int taska_stack[128];										/* Declare task A's stack */
	int taskb_stack[128];										/* Declare task B's stack */
	int taskc_stack[128];										/* Declare task C's stack */

	pit_init (500);												/* 500 µS = 0.5 milliseconds */
	taska_id = io_new_proc (taska, taska_stack, 128, 1);		/* Initialise task A */
	taskb_id = io_new_proc (taskb, taskb_stack, 128, 1);		/* Initialise task B */
	taskc_id = io_new_proc (taskc, taskc_stack, 128, 1);		/* Initialise task C */

	heater_on ();

	while (getc_nw () != 0x03) {								/* While ^C hasn't been pressed... */
		io_transfer (MAIN, taska_id, VECTOR_64);				/* Call task to get temperature */
		io_transfer (MAIN, taskb_id, VECTOR_64);				/* Call task to print it out */
		io_transfer (MAIN, taskc_id, VECTOR_64);				/* Call task to control the motor */
	}
}


void taska (void)
{
	for (;;)
		temperature = adc ();									/* Get the temperature */
}


void taskb (void)
{
	for (;;)
		printf ("The temperature is: $%x\n", temperature);		/* Print it out */
}


void taskc (void)
{
	for (;;)
		if (temperature > 75)									/* If (temperature > 75) turn on the motor */
			motor_forwards ();
		else
			motor_off ();
}
