/*
 * 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 set of functions to interface with the
 * PI/T chip on the Flight Board.
 *
 * (C) Copyright Rich Teer 1990, 2023, 2026.
 */

#include "pit.h"

static pit_t *pit = (pit_t *) 0x800000;

/*
 * Initialises PI/T ports
 */
void pit_init (int time)												/* Time slice in multiples of 20 microseconds */
{
	pit->pgcr = 0x00;													/* Reset pgcr */
	pit->pacr = 0x80;													/* pacr = submode 1X */
	pit->pbcr = 0x80;													/* pbcr = submode 1X */
	pit->paddr = 0xE0;													/* 3 MSBs of paddr are output, rest are input */
	pit->pbddr = 0xFF;													/* All of pbddr are outputs */
	pit->tivr = 0x40;													/* Interrupt vector = 64 */
	set_time_slice (time);												/* Set up the time slice */
	pit-> tcr = 0xA0;													/* Disable the timer for now */
	motor_off ();														/* Ensure the motor is off */
	heater_off ();														/* Ensure the heater is off */
}


void set_time_slice (int time)											/* Time slice in multiples of 20 microseconds */
{
	pit->tcr = 0xA0;													/* Control reg = %10100000 */
	time *= 5;															/* Convert us into clock ticks */
	pit->cprh = time / 65536;											/* Work out high order bits */
	pit->cprm = (time % 65536) / 256;									/* Work out middle order bits */
	pit->cprl = time % 256;											 	/* Work out low order bits */
	pit->tcr = 0xA1;													/* Control reg = %10100001 */
}


void motor_forwards (void)												/* Makes motor go forwards */
{
	pit->padr &= 0x30;													/* Reset 2 MSBs of padr */
	pit->padr |= 0x80;													/* Motor forwards */
}


void motor_backwards (void)											 	/* Makes motor go backwards */
{
	pit->padr &= 0x30;													/* Reset 2 MSBs of padr */
	pit->padr |= 0x40;													/* Motor backwards */
}


void motor_off (void)													/* Turns off the motor */
{
	pit->padr &= 0x30;													/* Reset 2 MSBs of padr */
}


void heater_on (void)													/* Turns on the heater */
{
	pit->padr |= 0x20;													/* Set bit 5 of padr */
}

void heater_off (void)													/* Turns off the heater */
{
	pit->padr &= 0xDF;													/* Reset bit 5 of padr */
}


int adc (void)															/* An ADC - assumes ports are already set up correctly */
{
	int test_value;
	int value_so_far;
	int current_bit;

	test_value = 0;
	value_so_far = 0;
	current_bit = 0x100;												/* Current bit = 256 */	
	do {
		current_bit >>= 1;												/* Divide current bit by 2 (rotate right 1 bit ) */
		test_value = current_bit + value_so_far;
		pit->pbdr = test_value;
		if (pit->padr & 0x08)											/* If comparator bit set, */
			value_so_far = test_value;									/* ... */
		test_value = 0;
	} while (current_bit != 0);

	return (value_so_far);
}
