view ds_hardware.c @ 75:0083b2f7b3c7

Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author Mike Pavone <pavone@retrodev.com>
date Tue, 06 Jul 2010 07:52:59 -0400
parents 76568becd6d6
children
line wrap: on
line source

#include <nds/interrupts.h>
#include <nds.h>
#include "datum.h"
#include "interp.h"
#include "structs.h"
#include <string.h>

#define IRQ_STUB(num) void irq_stub_##num () { rhope_irq(num); }

datum * irq_workers[MAX_INTERRUPTS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
program * irq_programs[MAX_INTERRUPTS];
worker_instance irq_instances[MAX_INTERRUPTS];
int irq_queue[MAX_INTERRUPTS];
int irq_queue_count = 0;

void rhope_irq(int num)
{
	if(num < MAX_INTERRUPTS && irq_workers[num])
	{
		if(irq_queue_count < MAX_INTERRUPTS)
			irq_queue[irq_queue_count++] = num;
		//TODO Add some kind of error handling for when the IRQ_QUEUE Is full?
	}
}

IRQ_STUB(0)
IRQ_STUB(1)
IRQ_STUB(2)
IRQ_STUB(3)
IRQ_STUB(4)
IRQ_STUB(5)
IRQ_STUB(6)
IRQ_STUB(7)
IRQ_STUB(8)
IRQ_STUB(9)
IRQ_STUB(10)
IRQ_STUB(11)
IRQ_STUB(12)
IRQ_STUB(13)
IRQ_STUB(14)
IRQ_STUB(15)
IRQ_STUB(16)
IRQ_STUB(17)
IRQ_STUB(18)
IRQ_STUB(19)
IRQ_STUB(20)
IRQ_STUB(21)
IRQ_STUB(22)
IRQ_STUB(23)
IRQ_STUB(24)




VoidFunctionPointer handlerList[MAX_INTERRUPTS] = {irq_stub_0,irq_stub_1,irq_stub_2,irq_stub_3,irq_stub_4,irq_stub_5,irq_stub_6,irq_stub_7,irq_stub_8,irq_stub_9,irq_stub_10,irq_stub_11,irq_stub_12,irq_stub_13,irq_stub_14,irq_stub_15,irq_stub_16,irq_stub_17,irq_stub_18,irq_stub_19,irq_stub_20,irq_stub_21,irq_stub_22,irq_stub_23,irq_stub_24};

int vis_register_handler(datum ** params, queue_entry * entry)
{
	int num = params[0]->c.integers.num_a;
	if(num >= MAX_INTERRUPTS)
	{
		release_ref(params[1]);
		params[1] = copy_datum(params[0], 0);
		params[0] = NULL;
		params[1]->c.integers.num_a = MAX_INTERRUPTS-1;
		return 0;
	}
	REG_IME = IME_DISABLE;
	if(irq_workers[num])
		release_ref(irq_workers[num]);
	irqSet(1<<num, handlerList[num]);
	irq_workers[num] = params[1];
	irq_programs[num] = entry->instance->def->program; //technically the worker could be from a different program than the one doing the registering, but it's doubtful
	irq_instances[num].def = irq_programs[num]->defs->deflist;
	irq_instances[num].caller_instance = NULL;
	irq_instances[num].trans = NULL;
	irq_instances[num].num_workers = irq_instances[num].num_wires = 0;
	VIS_InitializeCriticalSection(inst.counter_lock);
	REG_IME = IME_ENABLE;
	params[1] = NULL;
	return 0;
}

int vis_clear_handler(datum ** params, queue_entry * entry)
{
	int num = params[0]->c.integers.num_a;
	if(num >= MAX_INTERRUPTS)
	{
		release_ref(params[1]);
		params[1] = copy_datum(params[0], 0);
		params[0] = NULL;
		params[1]->c.integers.num_a = MAX_INTERRUPTS-1;
		return 0;
	}
	REG_IME = IME_DISABLE;
	if(irq_workers[num])
		release_ref(irq_workers[num]);
	irqClear(1<<num);
	irq_workers[num] = NULL;
	REG_IME = IME_ENABLE;
	params[1] = NULL;
	return 0;
}


void run_queued_irqs()
{
	int irq_queue_copy[MAX_INTERRUPTS];
	int irq_queue_count_copy;
	int i;
	queue_entry entry;
	datum * params[32];
	entry.worker_num = 0;
	//Could this result in missed interrupts or will they just be queued in hardware until I re-enable them?
	REG_IME = IME_DISABLE;
		irq_queue_count_copy = irq_queue_count;
		memcpy(irq_queue_copy, irq_queue, sizeof(int) * irq_queue_count);
		irq_queue_count = 0;
	REG_IME = IME_ENABLE;
	for(i = 0; i < irq_queue_count_copy; ++i)
	{
		params[0] = add_ref(irq_workers[irq_queue_copy[i]]);
		params[1] = create_list(irq_programs[irq_queue_copy[i]]);
		params[2] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, irq_programs[irq_queue_copy[i]]);
		params[2]->c.integers.num_a = irq_queue_copy[i];
		vis_list_append(params + 1, &entry);
		entry.instance = &irq_instances[irq_queue_copy[i]];
		entry.instance->in_progress_count = entry.instance->in_queue_count = 1000;
		vis_worker_do(params, &entry);
	}

}

const char ndsKeyLetters[15] = "ABESRLUD><XYMC";
#define NDS_MAX_KEY_BITS	14

int vis_held_keys(datum ** params, queue_entry * worker_entry)
{
	datum * workparams[3];
	datum * yes;
	char key_string[2] = " ";
	int held,i;
	scanKeys();
	held = keysHeld();
	workparams[0] = create_dict(worker_entry->instance->def->program);
	yes = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
	yes->c.integers.num_a = 1;
	for(i = 0; i < NDS_MAX_KEY_BITS; ++i)
		if(held & (1 << i))
		{
			key_string[0] = ndsKeyLetters[i];
			workparams[1] = make_string(key_string, -1, worker_entry->instance->def->program);
			workparams[2] = add_ref(yes);
			vis_dict_set(workparams, worker_entry);
		}
	params[0] = workparams[0];
	release_ref(yes);
	return 0;
}

int vis_touch_position(datum ** params, queue_entry * worker_entry)
{
	touchPosition touchXY;
	touchXY=touchReadXY();
	params[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
	params[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
	params[0]->c.integers.num_a = touchXY.px;
	params[1]->c.integers.num_a = touchXY.py;
	return 0;
}