Mercurial > repos > rhope
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; +}