view ds_hardware.c @ 187:5e752cf2d6b1

Add versions of compile and ctobin scripts that have desktop notifications
author Mike Pavone <pavone@retrodev.com>
date Fri, 07 Oct 2011 00:11:30 -0700
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;
}