diff ds_hardware.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ds_hardware.c	Tue Apr 28 23:06:07 2009 +0000
@@ -0,0 +1,170 @@
+#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;
+}