--- /dev/null
+Name: Generic Clock (compatible)\r
+ID: 0x12d0b402\r
+Version: 1\r
+\r
+Interrupts do different things depending on contents of the A register:\r
+\r
+ A | BEHAVIOR\r
+---+----------------------------------------------------------------------------\r
+ 0 | The B register is read, and the clock will tick 60/B times per second.\r
+ | If B is 0, the clock is turned off.\r
+ 1 | Store number of ticks elapsed since last call to 0 in C register\r
+ 2 | If register B is non-zero, turn on interrupts with message B. If B is zero,\r
+ | disable interrupts\r
+---+----------------------------------------------------------------------------\r
+\r
+When interrupts are enabled, the clock will trigger an interrupt whenever it\r
+ticks.\r
--- /dev/null
+Name: Generic Keyboard (compatible)\r
+ID: 0x30cf7406\r
+Version: 1\r
+\r
+Interrupts do different things depending on contents of the A register:\r
+\r
+ A | BEHAVIOR\r
+---+----------------------------------------------------------------------------\r
+ 0 | Clear keyboard buffer\r
+ 1 | Store next key typed in C register, or 0 if the buffer is empty\r
+ 2 | Set C register to 1 if the key specified by the B register is pressed, or\r
+ | 0 if it's not pressed\r
+ 3 | If register B is non-zero, turn on interrupts with message B. If B is zero,\r
+ | disable interrupts\r
+---+----------------------------------------------------------------------------\r
+\r
+When interrupts are enabled, the keyboard will trigger an interrupt when one or\r
+more keys have been pressed, released, or typed.\r
+\r
+Key numbers are:\r
+ 0x10: Backspace\r
+ 0x11: Return\r
+ 0x12: Insert\r
+ 0x13: Delete\r
+ 0x20-0x7f: ASCII characters\r
+ 0x80: Arrow up\r
+ 0x81: Arrow down\r
+ 0x82: Arrow left\r
+ 0x83: Arrow right\r
+ 0x90: Shift\r
+ 0x91: Control\r
--- /dev/null
+NE_LEM1802 v1.0\r
+ \r
+ \ | ___ \r
+ |\ \| ___ \r
+ | \\r
+\r
+ NYA ELEKTRISKA\r
+ innovation information\r
+\r
+\r
+\r
+\r
+DCPU-16 Hardware Info:\r
+ Name: LEM1802 - Low Energy Monitor\r
+ ID: 0x7349f615, version: 0x1802\r
+ Manufacturer: 0x1c6c8b36 (NYA_ELEKTRISKA)\r
+\r
+\r
+Description:\r
+ The LEM1802 is a 128x96 pixel color display compatible with the DCPU-16.\r
+ The display is made up of 32x12 16 bit cells. Each cell displays one\r
+ monochrome 4x8 pixel character out of 128 available. Each cell has its own\r
+ foreground and background color out of a palette of 16 colors.\r
+ \r
+ The LEM1802 is fully backwards compatible with LEM1801 (0x7349f615/0x1801),\r
+ and adds support for custom palettes and fixes the double buffer color\r
+ bleed bug. \r
+ \r
+\r
+Interrupt behavior:\r
+ When a HWI is received by the LEM1802, it reads the A register and does one\r
+ of the following actions:\r
+ \r
+ 0: MEM_MAP_SCREEN\r
+ Reads the B register, and maps the video ram to DCPU-16 ram starting\r
+ at address B. See below for a description of video ram.\r
+ If B is 0, the screen is disconnected.\r
+ When the screen goes from 0 to any other value, the the LEM1802 takes\r
+ about one second to start up. Other interrupts sent during this time\r
+ are still processed.\r
+ 1: MEM_MAP_FONT\r
+ Reads the B register, and maps the font ram to DCPU-16 ram starting\r
+ at address B. See below for a description of font ram.\r
+ If B is 0, the default font is used instead.\r
+ 2: MEM_MAP_PALETTE\r
+ Reads the B register, and maps the palette ram to DCPU-16 ram starting\r
+ at address B. See below for a description of palette ram.\r
+ If B is 0, the default palette is used instead.\r
+ 3: SET_BORDER_COLOR\r
+ Reads the B register, and sets the border color to palette index B&0xF\r
+ 4: MEM_DUMP_FONT\r
+ Reads the B register, and writes the default font data to DCPU-16 ram\r
+ starting at address B.\r
+ Halts the DCPU-16 for 256 cycles\r
+ 5: MEM_DUMP_PALETTE\r
+ Reads the B register, and writes the default palette data to DCPU-16\r
+ ram starting at address B. \r
+ Halts the DCPU-16 for 16 cycles\r
+\r
+\r
+Video ram:\r
+ The LEM1802 has no internal video ram, but rather relies on being assigned\r
+ an area of the DCPU-16 ram. The size of this area is 386 words, and is\r
+ made up of 32x12 cells of the following bit format (in LSB-0):\r
+ ffffbbbbBccccccc\r
+ The lowest 7 bits (ccccccc) select define character to display.\r
+ ffff and bbbb select which foreground and background color to use.\r
+ If B (bit 7) is set the character color will blink slowly.\r
+ \r
+\r
+Font ram:\r
+ The LEM1802 has a default built in font. If the user chooses, they may\r
+ supply their own font by mapping a 256 word memory region with two words\r
+ per character in the 128 character font.\r
+ By setting bits in these words, different characters and graphics can be\r
+ achieved. For example, the character F looks like this:\r
+ word0 = 1111111100001001\r
+ word1 = 0000100100000000\r
+ Or, split into octets:\r
+ word0 = 11111111 /\r
+ 00001001\r
+ word1 = 00001001 /\r
+ 00000000\r
+ \r
+\r
+Palette ram:\r
+ The LEM1802 has a default built in palette. If the user chooses, they may\r
+ supply their own palette by mapping a 16 word memory region with one word\r
+ per palette entry in the 16 color palette.\r
+ Each color entry has the following bit format (in LSB-0):\r
+ 0000rrrrggggbbbb\r
+ Where r, g, b are the red, green and blue channels. A higher value means a\r
+ lighter color.\r
+ \r
+\r
+A message from Ola:\r
+ Hello!\r
+ \r
+ It is fun to see that so many people use our products. When I was a small\r
+ boy, my dad used to tell me "Ola, take care of those who understand less\r
+ than you. Lack of knowledge is dangerous, but too much is worse". \r
+ Here at Nya Elektriska have we always tried to improve mankind by showing\r
+ them the tools required to improve and reach their true potential.\r
+ Together, you will wake up in time.\r
+ \r
+ - Ola Kristian Carlsson
\ No newline at end of file
--- /dev/null
+NE_SPC2000 v1.1\r
+ \r
+ \ | ___ \r
+ |\ \| ___ \r
+ | \\r
+\r
+ NYA ELEKTRISKA\r
+ innovation information\r
+\r
+\r
+DCPU-16 Hardware Info:\r
+ Name: SPC2000 - Suspension Chamber 2000\r
+ ID: 0x40e41d9d, version: 0x005e\r
+ Manufacturer: 0x1c6c8b36 (NYA_ELEKTRISKA)\r
+\r
+\r
+======================= WARNING WARNING WARNING WARNING ======================== \r
+ FERMIONS NEAR THE ACTIVATION RADIUS ARE CATASTROPHICALLY DESTROYED. DO NOT\r
+ USE NEAR EARTH OR MARS OR ANY OTHER FUTURE EARTH COLONIES. DO NOT TAMPER\r
+ WITH THE VACUUM DETECTOR. DO NOT USE IN AN UNEVEN GRAVITATIONAL FIELD. DO\r
+ NOT USE WHEN ROTATING. DO NOT USE WHEN ACCELERATING. ABSOLUTELY NO WARRANTY\r
+ IS PROVIDED, USE AT YOUR OWN RISK.\r
+ THE ZEF882 INCLUDED IN THIS SUSPENSION CHAMBER IS ILLEGAL IN ALL COUNTRIES.\r
+======================= WARNING WARNING WARNING WARNING ======================== \r
+\r
+Description:\r
+ The SPC2000 is a deep sleep cell based on the ZEF882 time dilation field\r
+ generator (available from Polytron Corporation Incorporated).\r
+ It provides safe and nearly instantaneous time passage, making long journeys\r
+ in space much easier on the passengers, and allowing cargo to reach its\r
+ destination with minimal aging occurring.\r
+ Due to the nature of the ZEF882, it affects the entire vessel (50 meter\r
+ radius, and will only engage in a near vacuum. Once the SPC2000 is active,\r
+ the vessel will be almost nowhere to an external observer, and detection of\r
+ the vessel is beyond unlikely.\r
+ Because of the strong extra-dimensional acceleration and non-linear temporal\r
+ distortion that occurs, it's highly recommended that passengers are strapped\r
+ in and asleep when triggering the SCP2000.\r
+ \r
+\r
+Improvements:\r
+ * Added the ability to set the unit to skip to something other than the\r
+ default setting of milliseconds.\r
+ \r
+ \r
+Interrupt behavior:\r
+ When a HWI is received by the SPC2000, it reads the A register and does one\r
+ of the following actions:\r
+ \r
+ 0: GET_STATUS\r
+ Sets the C register to 1 if the SPC2000 is ready to trigger. If it's not,\r
+ the B register is set to one of the following values:\r
+ 0x0000: ######################## - EVACUATE VESSEL IMMEDIATELY\r
+ 0x0001: Not in a vacuum\r
+ 0x0002: Not enough fuel\r
+ 0x0003: Gravitational forces too uneven\r
+ 0x0004: Too much angular momentum\r
+ 0x0005: One or more cell doors are open\r
+ 0x0006: Mechanical error\r
+ 0xffff: Unknown error - EVACUATE VESSEL IMMEDIATELY\r
+ 1: SET_UNIT_TO_SKIP\r
+ Reads the B register, and reads a 64 bit number from memory address B\r
+ in big endian, and sets the number of units to skip to that number.\r
+ 2: TRIGGER_DEVICE\r
+ Performs GET_STATUS, and if C is 0, triggers the SCP2000. The status can\r
+ be read as the result of the GET_STATUS call.\r
+ 3: SET_SKIP_UNIT\r
+ Reads the B register, and sets the size of the unit to skip to one of:\r
+ 0x0000: Milliseconds\r
+ 0x0001: Minutes\r
+ 0x0002: Days\r
+ 0x0003: Years\r
+ \r
+ \r
+A message from Ola:\r
+ Good morning,\r
+ \r
+ Thanks for purchasing this piece of hardware! I hope it will enlighten you\r
+ and give you new hope in life. As this suspension chamber basically works as\r
+ a one way time machine, I suppose I should wish you a pleasant journey, and\r
+ ask of you to enjoy the future. It is yours now. All of it.\r
+ \r
+ - Ola Kristian Carlsson\r
+
\ No newline at end of file
--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "dcpu16.h"
+#include "hw_spc2000.h"
+
+static dcpu16_hw_signal_t spc2000_reset_;
+static dcpu16_hw_signal_t spc2000_cycle_;
+static dcpu16_hw_signal_t spc2000_hwi_;
+static struct dcpu16_hw hw_ = {
+ .name_ = "SPC2000 - Suspension Chamber 2000",
+ .id_l = 0x1d9d,
+ .id_h = 0x40e4,
+ .ver = 0x005e,
+ .mfg_l = 0x8b36,
+ .mfg_h = 0x1c6c,
+ .hwi = spc2000_hwi_,
+ .cycle = spc2000_cycle_,
+ .reset = spc2000_reset_,
+ .data = (struct spc2000_ *)NULL
+};
+
+struct spc2000_ {
+ DCPU16_WORD skip_unit;
+ long long skip;
+};
+
+static
+void spc2000_reset_(struct dcpu16 *vm, void *data) {
+ struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+
+ (void)vm;
+
+ memset(spc2000, 0, sizeof *spc2000);
+}
+
+static
+void spc2000_cycle_(struct dcpu16 *vm, void *data) {
+ struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+
+ (void)vm;
+ (void)spc2000;
+}
+
+static
+void spc2000_hwi_(struct dcpu16 *vm, void *data) {
+ struct spc2000_ *spc2000 = (struct spc2000_ *)data;
+ DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A],
+ reg_b = vm->reg[DCPU16_REG_B];
+ long long x;
+
+ switch (reg_a) {
+ case 0: /* GET_STATUS */
+ case 2: /* TRIGGER_DEVICE */
+ /* check status */
+ vm->reg[DCPU16_REG_C] = 0;
+ vm->reg[DCPU16_REG_B] = 0;
+ if (reg_a == 0
+ || vm->reg[DCPU16_REG_C] != 0)
+ break;
+ /* trigger */
+ vm->warn_cb_("spc2000 triggered\n");
+ break;
+
+ case 1: /* SET_UNIT_TO_SKIP */
+ spc2000->skip = vm->ram[reg_b];
+ x = vm->ram[reg_b + 1];
+ spc2000->skip |= x << 16;
+ x = vm->ram[reg_b + 2];
+ spc2000->skip |= x << 32;
+ x = vm->ram[reg_b + 3];
+ spc2000->skip |= x << 48;
+ break;
+
+ case 3: /* SET_SKIP_UNIT */
+ spc2000->skip_unit = reg_b;
+ break;
+ }
+}
--- /dev/null
+#ifndef SPC2000_H_IE4EG0MO
+#define SPC2000_H_IE4EG0MO
+
+struct dcpu16_hw *spc2000_new(struct dcpu16 *);
+void spc2000_del(struct dcpu16_hw **);
+
+#endif /* SPC2000_H_IE4EG0MO */
--- /dev/null
+; bare-bones test to locate, activate, and write to a display
+
+HWN [num]
+:loop
+ SUB [num], 1
+ HWQ [num]
+ IFE B, 0x7349
+ SET PC, found
+ SET PC, loop
+
+:found
+ ; located the first display, power it on
+ SET B, 0x8000
+ SET A, 0
+ HWI [num]
+
+ ; set border
+ SET B, 0x0003
+ SET A, 3
+ HWI [num]
+
+ ; show some text
+ SET I, string
+ SET J, 0x8000
+ ; color
+ SET Z, 0x1e00
+:print
+ BOR [i], Z
+ STI [j], [i]
+ IFN [I], 0
+ SET PC, print
+
+:wait
+ SET PC, wait
+
+:num dat 0x0000
+:string dat "yerf!", 0
\ No newline at end of file