diff --git a/cores/Spectrum/coreid.v b/cores/Spectrum/coreid.v new file mode 100644 index 0000000..873b4ab --- /dev/null +++ b/cores/Spectrum/coreid.v @@ -0,0 +1,70 @@ +`timescale 1ns / 1ps +`default_nettype none + +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 18:22:21 06/07/2015 +// Design Name: +// Module Name: coreid +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module coreid ( + input wire clk, + input wire rst_n, + input wire [7:0] zxuno_addr, + input wire zxuno_regrd, + input wire regaddr_changed, + output wire [7:0] dout, + output wire oe_n + ); + + reg [7:0] text[0:15]; + integer i; + initial begin + for (i=0;i<16;i=i+1) + text[i] = 8'h00; + text[ 0] = "T"; + text[ 1] = "1"; + text[ 2] = "6"; + text[ 3] = "-"; + text[ 4] = "1"; + text[ 5] = "4"; + text[ 6] = "0"; + text[ 7] = "6"; + text[ 8] = "2"; + text[ 9] = "0"; + text[10] = "1"; + text[11] = "5"; + end + + reg [3:0] textindx = 4'h0; + reg reading = 1'b0; + assign oe_n = !(zxuno_addr == 8'hFF && zxuno_regrd==1'b1); + assign dout = (oe_n==1'b0)? text[textindx] : 8'hZZ; + + always @(posedge clk) begin + if (rst_n == 1'b0 || (regaddr_changed==1'b1 && zxuno_addr==8'hFF)) begin + textindx <= 4'h0; + reading <= 1'b0; + end + else if (oe_n==1'b0) begin + reading <= 1'b1; + end + else if (reading == 1'b1 && oe_n==1'b1) begin + reading <= 1'b0; + textindx <= textindx + 1; + end + end +endmodule diff --git a/cores/Spectrum/genkeybmap_es.c b/cores/Spectrum/genkeybmap_es.c new file mode 100644 index 0000000..c23e45b --- /dev/null +++ b/cores/Spectrum/genkeybmap_es.c @@ -0,0 +1,488 @@ +#include +#include + +typedef unsigned char BYTE; +/* + 8 8 3 5 3 5 +AAADDDDD AAADDDDD MRN JJJJJ MMM XXXXX + +AAA = semifila del teclado a modificar | esta información está +DDDDD = dato (AND negado con lo que haya) de esa semifila | repetida para dos teclas +MRN = Master reset, Reset de usuario, NMI +JJJJJ = estado del joystick al pulsar tecla. Posiciones UDLRX +MMM = la tecla es un modificador +XXXXX = Reservado para uso futuro + +Ej: en la dirección de memoria correspondiente al código de la tecla ESC, +que correspondería a la pulsación simultánea de CAPS SHIFT+SPACE, pondríamos: +00000001 11100001 000 00000 000 00000 +Esto es: se activan las semifilas 0 y 7, y en cada una, se activa el bit 0 + +256 codigos + E0 = 512 codigos +SHIFT, CTRL, ALT = 8 combinaciones + +512*8=4096 direcciones x 32 bits = 16384 bytes +En el core se dispondrá como una memoria de 16384x8 bits + +Cada tecla ocupará cuatro direcciones consecutivas. +D+0 : tecla1 (o 0 si no la hay) +D+1 : tecla2 (o 0 si no la hay) +D+2 : señales de reset y joystick, 0 si no hay +D+3 : modificadores y señales de usuario, 0 si no hay +*/ + +// You shouldn't have to touch these defs unless your Spectrum has a different keyboard +// layout (because, for example, you are using a different ROM + +#define SP_1 0x61 +#define SP_2 0x62 +#define SP_3 0x64 +#define SP_4 0x68 +#define SP_5 0x70 + +#define SP_0 0x81 +#define SP_9 0x82 +#define SP_8 0x84 +#define SP_7 0x88 +#define SP_6 0x90 + +#define SP_Q 0x41 +#define SP_W 0x42 +#define SP_E 0x44 +#define SP_R 0x48 +#define SP_T 0x50 + +#define SP_P 0xA1 +#define SP_O 0xA2 +#define SP_I 0xA4 +#define SP_U 0xA8 +#define SP_Y 0xB0 + +#define SP_A 0x21 +#define SP_S 0x22 +#define SP_D 0x24 +#define SP_F 0x28 +#define SP_G 0x30 + +#define SP_ENTER 0xC1 +#define SP_L 0xC2 +#define SP_K 0xC4 +#define SP_J 0xC8 +#define SP_H 0xD0 + +#define SP_CAPS 0x01 +#define SP_Z 0x02 +#define SP_X 0x04 +#define SP_C 0x08 +#define SP_V 0x10 + +#define SP_SPACE 0xE1 +#define SP_SYMBOL 0xE2 +#define SP_M 0xE4 +#define SP_N 0xE8 +#define SP_B 0xF0 + +#define SP_BANG (SP_SYMBOL<<8) | SP_1 +#define SP_AT (SP_SYMBOL<<8) | SP_2 +#define SP_HASH (SP_SYMBOL<<8) | SP_3 +#define SP_DOLLAR (SP_SYMBOL<<8) | SP_4 +#define SP_PERCEN (SP_SYMBOL<<8) | SP_5 +#define SP_AMP (SP_SYMBOL<<8) | SP_6 +#define SP_APOSTRO (SP_SYMBOL<<8) | SP_7 +#define SP_PAROPEN (SP_SYMBOL<<8) | SP_8 +#define SP_PARCLOS (SP_SYMBOL<<8) | SP_9 +#define SP_UNDERSC (SP_SYMBOL<<8) | SP_0 +#define SP_LESS (SP_SYMBOL<<8) | SP_R +#define SP_LESSEQ (SP_SYMBOL<<8) | SP_Q +#define SP_GREATER (SP_SYMBOL<<8) | SP_T +#define SP_GREATEQ (SP_SYMBOL<<8) | SP_E +#define SP_NOTEQ (SP_SYMBOL<<8) | SP_W +#define SP_BRAOPEN (SP_SYMBOL<<8) | SP_Y +#define SP_BRACLOS (SP_SYMBOL<<8) | SP_U +#define SP_SEMICOL (SP_SYMBOL<<8) | SP_O +#define SP_QUOTE (SP_SYMBOL<<8) | SP_P +#define SP_TILDE (SP_SYMBOL<<8) | SP_A +#define SP_PIPE (SP_SYMBOL<<8) | SP_S +#define SP_BACKSLA (SP_SYMBOL<<8) | SP_D +#define SP_CUROPEN (SP_SYMBOL<<8) | SP_F +#define SP_CURCLOS (SP_SYMBOL<<8) | SP_G +#define SP_CARET (SP_SYMBOL<<8) | SP_H +#define SP_MINUS (SP_SYMBOL<<8) | SP_J +#define SP_PLUS (SP_SYMBOL<<8) | SP_K +#define SP_EQUAL (SP_SYMBOL<<8) | SP_L +#define SP_COLON (SP_SYMBOL<<8) | SP_Z +#define SP_POUND (SP_SYMBOL<<8) | SP_X +#define SP_QUEST (SP_SYMBOL<<8) | SP_C +#define SP_SLASH (SP_SYMBOL<<8) | SP_V +#define SP_STAR (SP_SYMBOL<<8) | SP_B +#define SP_COMMA (SP_SYMBOL<<8) | SP_N +#define SP_DOT (SP_SYMBOL<<8) | SP_M + +#define SP_EXTEND (SP_CAPS<<8) | SP_SYMBOL +#define SP_EDIT (SP_CAPS<<8) | SP_1 +#define SP_CPSLOCK (SP_CAPS<<8) | SP_2 +#define SP_TRUE (SP_CAPS<<8) | SP_3 +#define SP_INVERSE (SP_CAPS<<8) | SP_4 +#define SP_LEFT (SP_CAPS<<8) | SP_5 +#define SP_DOWN (SP_CAPS<<8) | SP_6 +#define SP_UP (SP_CAPS<<8) | SP_7 +#define SP_RIGHT (SP_CAPS<<8) | SP_8 +#define SP_GRAPH (SP_CAPS<<8) | SP_9 +#define SP_DELETE (SP_CAPS<<8) | SP_0 +#define SP_BREAK (SP_CAPS<<8) | SP_SPACE + +// END of Spectrum keys definitions + +// Definitions for additional signals generated by the keyboard core +// AAADDDDD AAADDDDD MRN JJJJJ MMM XXXXX +#define MODIFIER1 0x20 +#define MODIFIER2 0x40 +#define MODIFIER3 0x80 + +#define MRESET 0x80 +#define URESET 0x40 +#define NMI 0x20 + +#define JOYUP 0x10 +#define JOYDOWN 0x08 +#define JOYLEFT 0x04 +#define JOYRIGHT 0x02 +#define JOYFIRE 0x01 + +#define USER1 0x10 +#define USER2 0x08 +#define USER3 0x04 +#define USER4 0x02 +#define USER5 0x01 +// End of additional signals + +// A key can be pressed with up to three key modifiers +// which generates 8 combinations for each key +#define EXT 0x100 +#define MD1 0x200 +#define MD2 0x400 +#define MD3 0x800 + +// Scan code 2 list. First, non localized keys +#define PC_A 0x1C +#define PC_B 0x32 +#define PC_C 0x21 +#define PC_D 0x23 +#define PC_E 0x24 +#define PC_F 0x2B +#define PC_G 0x34 +#define PC_H 0x33 +#define PC_I 0x43 +#define PC_J 0x3B +#define PC_K 0x42 +#define PC_L 0x4B +#define PC_M 0x3A +#define PC_N 0x31 +#define PC_O 0x44 +#define PC_P 0x4D +#define PC_Q 0x15 +#define PC_R 0x2D +#define PC_S 0x1B +#define PC_T 0x2C +#define PC_U 0x3C +#define PC_V 0x2A +#define PC_W 0x1D +#define PC_X 0x22 +#define PC_Y 0x35 +#define PC_Z 0x1A + +#define PC_0 0x45 +#define PC_1 0x16 +#define PC_2 0x1E +#define PC_3 0x26 +#define PC_4 0x25 +#define PC_5 0x2E +#define PC_6 0x36 +#define PC_7 0x3D +#define PC_8 0x3E +#define PC_9 0x46 + +#define PC_F1 0x05 +#define PC_F2 0x06 +#define PC_F3 0x04 +#define PC_F4 0x0C +#define PC_F5 0x03 +#define PC_F6 0x0B +#define PC_F7 0x83 +#define PC_F8 0x0A +#define PC_F9 0x01 +#define PC_F10 0x09 +#define PC_F11 0x78 +#define PC_F12 0x07 + +#define PC_ESC 0x76 +#define PC_SPACE 0x29 +#define PC_LCTRL 0x14 +#define PC_RCTRL 0x14 | EXT +#define PC_LSHIFT 0x12 +#define PC_RSHIFT 0x59 +#define PC_LALT 0x11 +#define PC_RALT 0x11 | EXT +#define PC_LWIN 0x1F | EXT +#define PC_RWIN 0x27 | EXT +#define PC_APPS 0x2F | EXT + +#define PC_TAB 0x0D +#define PC_CPSLOCK 0x58 +#define PC_SCRLOCK 0x7E + +#define PC_INSERT 0x70 | EXT +#define PC_DELETE 0x71 | EXT +#define PC_HOME 0x6C | EXT +#define PC_END 0x69 | EXT +#define PC_PGUP 0x7D | EXT +#define PC_PGDOWN 0x7A | EXT +#define PC_BKSPACE 0x66 +#define PC_ENTER 0x5A +#define PC_UP 0x75 | EXT +#define PC_DOWN 0x72 | EXT +#define PC_LEFT 0x6B | EXT +#define PC_RIGHT 0x74 | EXT + +#define PC_NUMLOCK 0x77 +#define PC_KP_DIVIS 0x4A | EXT +#define PC_KP_MULT 0x7C +#define PC_KP_MINUS 0x7B +#define PC_KP_PLUS 0x79 +#define PC_KP_ENTER 0x5A | EXT +#define PC_KP_DOT 0x71 +#define PC_KP_0 0x70 +#define PC_KP_1 0x69 +#define PC_KP_2 0x72 +#define PC_KP_3 0x7A +#define PC_KP_4 0x6B +#define PC_KP_5 0x73 +#define PC_KP_6 0x74 +#define PC_KP_7 0x6C +#define PC_KP_8 0x75 +#define PC_KP_9 0x7D + +// Localized keyboards start to differenciate from here + +// Localized keyboard ES (Spain) +#define PC_BACKSLA 0x0E +#define PC_APOSTRO 0x4E +#define PC_OPNBANG 0x55 +#define PC_GRAVEAC 0x54 +#define PC_PLUS 0x5B +#define PC_EGNE 0x4C +#define PC_ACUTEAC 0x52 +#define PC_CEDILLA 0x5D +#define PC_LESS 0x61 +#define PC_COMMA 0x41 +#define PC_DOT 0x49 +#define PC_MINUS 0x4A + +#define MAP(pc,sp,rj,mu) { \ + rom[(pc)*4] = (((sp)>>8)&0xFF); \ + rom[(pc)*4+1] = (((sp))&0xFF); \ + rom[(pc)*4+2] = (rj); \ + rom[(pc)*4+3] = (mu); \ + } + +#define MAPANY(pc,sp,rj,mu) { \ + MAP(pc,sp,rj,mu); \ + MAP(MD1|pc,sp,rj,mu); \ + MAP(MD2|pc,sp,rj,mu); \ + MAP(MD3|pc,sp,rj,mu); \ + MAP(MD1|MD2|pc,sp,rj,mu); \ + MAP(MD1|MD3|pc,sp,rj,mu); \ + MAP(MD2|MD3|pc,sp,rj,mu); \ + MAP(MD1|MD2|MD3|pc,sp,rj,mu); \ + } + +#define CLEANMAP { \ + int i; \ + for (i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \ + rom[i] = 0; \ + } +#define SAVEMAPHEX(name) { \ + FILE *f; \ + int i; \ + f=fopen(name,"w"); \ + for(i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \ + fprintf(f,"%.2X\n",rom[i]); \ + fclose(f); \ + } + +#define SAVEMAPBIN(name) { \ + FILE *f; \ + int i; \ + f=fopen(name,"wb"); \ + fwrite (rom, 1, sizeof(rom), f); \ + fclose(f); \ + } + + +int main() +{ + BYTE rom[16384]; + + CLEANMAP; + + MAPANY(PC_LSHIFT,0,0,MODIFIER1); // MD1 is SHIFT + MAPANY(PC_RSHIFT,0,0,MODIFIER1); // MD1 is SHIFT + MAPANY(PC_LCTRL,0,0,MODIFIER2); // MD2 is CTRL + MAPANY(PC_RCTRL,0,0,MODIFIER2); // MD2 is CTRL + MAPANY(PC_LALT,0,JOYFIRE,MODIFIER3); // MD3 is ALT. Also is FIRE for keyboard joystick + MAPANY(PC_RALT,0,JOYFIRE,MODIFIER3); // MD3 is ALT. Also is FIRE for keyboard joystick + + MAPANY(PC_LWIN,SP_CAPS,0,0); // CAPS SHIFT + MAPANY(PC_RWIN,SP_SYMBOL,0,0); // SYMBOL SHIFT + + // Basic mapping: each key from PC is mapped to a key in the Spectrum + MAP(PC_1,SP_1,0,0); + MAP(PC_2,SP_2,0,0); + MAP(PC_3,SP_3,0,0); + MAP(PC_4,SP_4,0,0); + MAP(PC_5,SP_5,0,0); + MAP(PC_6,SP_6,0,0); + MAP(PC_7,SP_7,0,0); + MAP(PC_8,SP_8,0,0); + MAP(PC_9,SP_9,0,0); + MAP(PC_0,SP_0,0,0); + + MAP(PC_Q,SP_Q,0,0); + MAP(PC_W,SP_W,0,0); + MAP(PC_E,SP_E,0,0); + MAP(PC_R,SP_R,0,0); + MAP(PC_T,SP_T,0,0); + MAP(PC_Y,SP_Y,0,0); + MAP(PC_U,SP_U,0,0); + MAP(PC_I,SP_I,0,0); + MAP(PC_O,SP_O,0,0); + MAP(PC_P,SP_P,0,0); + MAP(PC_A,SP_A,0,0); + MAP(PC_S,SP_S,0,0); + MAP(PC_D,SP_D,0,0); + MAP(PC_F,SP_F,0,0); + MAP(PC_G,SP_G,0,0); + MAP(PC_H,SP_H,0,0); + MAP(PC_J,SP_J,0,0); + MAP(PC_K,SP_K,0,0); + MAP(PC_L,SP_L,0,0); + MAP(PC_Z,SP_Z,0,0); + MAP(PC_X,SP_X,0,0); + MAP(PC_C,SP_C,0,0); + MAP(PC_V,SP_V,0,0); + MAP(PC_B,SP_B,0,0); + MAP(PC_N,SP_N,0,0); + MAP(PC_M,SP_M,0,0); + + MAP(MD1|PC_Q,SP_CAPS<<8|SP_Q,0,0); + MAP(MD1|PC_W,SP_CAPS<<8|SP_W,0,0); + MAP(MD1|PC_E,SP_CAPS<<8|SP_E,0,0); + MAP(MD1|PC_R,SP_CAPS<<8|SP_R,0,0); + MAP(MD1|PC_T,SP_CAPS<<8|SP_T,0,0); + MAP(MD1|PC_Y,SP_CAPS<<8|SP_Y,0,0); + MAP(MD1|PC_U,SP_CAPS<<8|SP_U,0,0); + MAP(MD1|PC_I,SP_CAPS<<8|SP_I,0,0); + MAP(MD1|PC_O,SP_CAPS<<8|SP_O,0,0); + MAP(MD1|PC_P,SP_CAPS<<8|SP_P,0,0); + MAP(MD1|PC_A,SP_CAPS<<8|SP_A,0,0); + MAP(MD1|PC_S,SP_CAPS<<8|SP_S,0,0); + MAP(MD1|PC_D,SP_CAPS<<8|SP_D,0,0); + MAP(MD1|PC_F,SP_CAPS<<8|SP_F,0,0); + MAP(MD1|PC_G,SP_CAPS<<8|SP_G,0,0); + MAP(MD1|PC_H,SP_CAPS<<8|SP_H,0,0); + MAP(MD1|PC_J,SP_CAPS<<8|SP_J,0,0); + MAP(MD1|PC_K,SP_CAPS<<8|SP_K,0,0); + MAP(MD1|PC_L,SP_CAPS<<8|SP_L,0,0); + MAP(MD1|PC_Z,SP_CAPS<<8|SP_Z,0,0); + MAP(MD1|PC_X,SP_CAPS<<8|SP_X,0,0); + MAP(MD1|PC_C,SP_CAPS<<8|SP_C,0,0); + MAP(MD1|PC_V,SP_CAPS<<8|SP_V,0,0); + MAP(MD1|PC_B,SP_CAPS<<8|SP_B,0,0); + MAP(MD1|PC_N,SP_CAPS<<8|SP_N,0,0); + MAP(MD1|PC_M,SP_CAPS<<8|SP_M,0,0); + + MAPANY(PC_SPACE,SP_SPACE,0,0); + MAPANY(PC_ENTER,SP_ENTER,0,0); + + //Complex mapping. This is for the spanish keyboard although many + //combos can be used with any other PC keyboard + MAPANY(PC_ESC,SP_BREAK,0,0); + MAPANY(PC_CPSLOCK,SP_CPSLOCK,0,0); + MAPANY(PC_TAB,SP_EXTEND,0,0); + MAP(PC_BKSPACE,SP_DELETE,0,0); + MAPANY(PC_UP,SP_UP,0,0); + MAPANY(PC_DOWN,SP_DOWN,0,0); + MAPANY(PC_LEFT,SP_LEFT,0,0); + MAPANY(PC_RIGHT,SP_RIGHT,0,0); + MAPANY(PC_F2,SP_EDIT,0,0); + + MAP(PC_F5|MD2|MD3,0,NMI,0); // Ctrl-Alt-F5 for NMI + MAP(PC_F10,SP_GRAPH,0,0); // F10 habilita el modo gráfico. Esto es para Antonio, para la BIOS + MAP(PC_DELETE|MD2|MD3,0,URESET,0); // + MAP(PC_KP_DOT|MD2|MD3,0,URESET,0); // Ctrl-Alt-Del for user reset + MAP(PC_BKSPACE|MD2|MD3,0,MRESET,0); // Ctrl-Alt-BkSpace for master reset + + //keypad + MAPANY(PC_KP_DIVIS,SP_SLASH,0,0); + MAPANY(PC_KP_MULT,SP_STAR,0,0); + MAPANY(PC_KP_MINUS,SP_MINUS,0,0); + MAPANY(PC_KP_PLUS,SP_PLUS,0,0); + MAPANY(PC_KP_ENTER,SP_ENTER,0,0); + + // a 8-way keyboard joystick on the keypad + MAPANY(PC_KP_7,0,JOYUP|JOYLEFT,0); + MAPANY(PC_KP_8,0,JOYUP,0); + MAPANY(PC_KP_9,0,JOYUP|JOYRIGHT,0); + MAPANY(PC_KP_4,0,JOYLEFT,0); + MAPANY(PC_KP_5,0,JOYDOWN,0); + MAPANY(PC_KP_6,0,JOYRIGHT,0); + MAPANY(PC_KP_1,0,JOYDOWN|JOYLEFT,0); + MAPANY(PC_KP_2,0,JOYDOWN,0); + MAPANY(PC_KP_3,0,JOYDOWN|JOYRIGHT,0); + + //Some shift+key mappings for the ES keyboard + MAP(MD1|PC_1,SP_BANG,0,0); + MAP(MD1|PC_2,SP_QUOTE,0,0); + MAP(MD1|PC_3,SP_HASH,0,0); + MAP(MD1|PC_4,SP_DOLLAR,0,0); + MAP(MD1|PC_5,SP_PERCEN,0,0); + MAP(MD1|PC_6,SP_AMP,0,0); + MAP(MD1|PC_7,SP_SLASH,0,0); + MAP(MD1|PC_8,SP_PAROPEN,0,0); + MAP(MD1|PC_9,SP_PARCLOS,0,0); + MAP(MD1|PC_0,SP_EQUAL,0,0); + MAP(PC_APOSTRO,SP_APOSTRO,0,0); + MAP(MD1|PC_APOSTRO,SP_QUEST,0,0); + MAP(PC_GRAVEAC,SP_POUND,0,0); + MAP(MD1|PC_GRAVEAC,SP_CARET,0,0); + MAP(PC_PLUS,SP_PLUS,0,0); + MAP(MD1|PC_PLUS,SP_STAR,0,0); + MAP(PC_ACUTEAC,SP_CUROPEN,0,0); + MAP(MD1|PC_ACUTEAC,SP_CUROPEN,0,0); + MAP(PC_ACUTEAC,SP_CUROPEN,0,0); + MAP(MD1|PC_ACUTEAC,SP_CUROPEN,0,0); + MAP(PC_CEDILLA,SP_CURCLOS,0,0); + MAP(MD1|PC_CEDILLA,SP_QUOTE,0,0); + MAP(PC_COMMA,SP_COMMA,0,0); + MAP(MD1|PC_COMMA,SP_SEMICOL,0,0); + MAP(PC_DOT,SP_DOT,0,0); + MAP(MD1|PC_DOT,SP_COLON,0,0); + MAP(PC_MINUS,SP_MINUS,0,0); + MAP(MD1|PC_MINUS,SP_UNDERSC,0,0); + MAP(PC_BACKSLA,SP_BACKSLA,0,0); + MAP(MD1|PC_BACKSLA,SP_BACKSLA,0,0); + MAP(PC_EGNE,SP_TILDE,0,0); + MAP(PC_LESS,SP_LESS,0,0); + MAP(MD1|PC_LESS,SP_GREATER,0,0); + MAP(MD2|PC_LESS,SP_LESSEQ,0,0); + MAP(MD2|MD1|PC_LESS,SP_GREATEQ,0,0); + MAP(MD3|PC_LESS,SP_NOTEQ,0,0); + MAP(MD3|MD1|PC_LESS,SP_NOTEQ,0,0); + MAP(MD3|MD2|PC_LESS,SP_NOTEQ,0,0); + MAP(MD3|MD2|MD1|PC_LESS,SP_NOTEQ,0,0); + + // End of mapping. Save .HEX file for Verilog + SAVEMAPHEX("keyb_es_hex.txt"); + // And map file for loading from ESXDOS + SAVEMAPBIN("keymaps\\ES"); +} diff --git a/cores/Spectrum/genkeybmap_us.c b/cores/Spectrum/genkeybmap_us.c new file mode 100644 index 0000000..b6a1208 --- /dev/null +++ b/cores/Spectrum/genkeybmap_us.c @@ -0,0 +1,479 @@ +#include +#include + +typedef unsigned char BYTE; +/* + 8 8 3 5 3 5 +AAADDDDD AAADDDDD MRN JJJJJ MMM XXXXX + +AAA = semifila del teclado a modificar | esta información está +DDDDD = dato (AND negado con lo que haya) de esa semifila | repetida para dos teclas +MRN = Master reset, Reset de usuario, NMI +JJJJJ = estado del joystick al pulsar tecla. Posiciones UDLRX +MMM = la tecla es un modificador +XXXXX = Reservado para uso futuro + +Ej: en la dirección de memoria correspondiente al código de la tecla ESC, +que correspondería a la pulsación simultánea de CAPS SHIFT+SPACE, pondríamos: +00000001 11100001 000 00000 000 00000 +Esto es: se activan las semifilas 0 y 7, y en cada una, se activa el bit 0 + +256 codigos + E0 = 512 codigos +SHIFT, CTRL, ALT = 8 combinaciones + +512*8=4096 direcciones x 32 bits = 16384 bytes +En el core se dispondrá como una memoria de 16384x8 bits + +Cada tecla ocupará cuatro direcciones consecutivas. +D+0 : tecla1 (o 0 si no la hay) +D+1 : tecla2 (o 0 si no la hay) +D+2 : señales de reset y joystick, 0 si no hay +D+3 : modificadores y señales de usuario, 0 si no hay +*/ + +// You shouldn't have to touch these defs unless your Spectrum has a different keyboard +// layout (because, for example, you are using a different ROM + +#define SP_1 0x61 +#define SP_2 0x62 +#define SP_3 0x64 +#define SP_4 0x68 +#define SP_5 0x70 + +#define SP_0 0x81 +#define SP_9 0x82 +#define SP_8 0x84 +#define SP_7 0x88 +#define SP_6 0x90 + +#define SP_Q 0x41 +#define SP_W 0x42 +#define SP_E 0x44 +#define SP_R 0x48 +#define SP_T 0x50 + +#define SP_P 0xA1 +#define SP_O 0xA2 +#define SP_I 0xA4 +#define SP_U 0xA8 +#define SP_Y 0xB0 + +#define SP_A 0x21 +#define SP_S 0x22 +#define SP_D 0x24 +#define SP_F 0x28 +#define SP_G 0x30 + +#define SP_ENTER 0xC1 +#define SP_L 0xC2 +#define SP_K 0xC4 +#define SP_J 0xC8 +#define SP_H 0xD0 + +#define SP_CAPS 0x01 +#define SP_Z 0x02 +#define SP_X 0x04 +#define SP_C 0x08 +#define SP_V 0x10 + +#define SP_SPACE 0xE1 +#define SP_SYMBOL 0xE2 +#define SP_M 0xE4 +#define SP_N 0xE8 +#define SP_B 0xF0 + +#define SP_BANG (SP_SYMBOL<<8) | SP_1 +#define SP_AT (SP_SYMBOL<<8) | SP_2 +#define SP_HASH (SP_SYMBOL<<8) | SP_3 +#define SP_DOLLAR (SP_SYMBOL<<8) | SP_4 +#define SP_PERCEN (SP_SYMBOL<<8) | SP_5 +#define SP_AMP (SP_SYMBOL<<8) | SP_6 +#define SP_APOSTRO (SP_SYMBOL<<8) | SP_7 +#define SP_PAROPEN (SP_SYMBOL<<8) | SP_8 +#define SP_PARCLOS (SP_SYMBOL<<8) | SP_9 +#define SP_UNDERSC (SP_SYMBOL<<8) | SP_0 +#define SP_LESS (SP_SYMBOL<<8) | SP_R +#define SP_LESSEQ (SP_SYMBOL<<8) | SP_Q +#define SP_GREATER (SP_SYMBOL<<8) | SP_T +#define SP_GREATEQ (SP_SYMBOL<<8) | SP_E +#define SP_NOTEQ (SP_SYMBOL<<8) | SP_W +#define SP_BRAOPEN (SP_SYMBOL<<8) | SP_Y +#define SP_BRACLOS (SP_SYMBOL<<8) | SP_U +#define SP_SEMICOL (SP_SYMBOL<<8) | SP_O +#define SP_QUOTE (SP_SYMBOL<<8) | SP_P +#define SP_TILDE (SP_SYMBOL<<8) | SP_A +#define SP_PIPE (SP_SYMBOL<<8) | SP_S +#define SP_BACKSLA (SP_SYMBOL<<8) | SP_D +#define SP_CUROPEN (SP_SYMBOL<<8) | SP_F +#define SP_CURCLOS (SP_SYMBOL<<8) | SP_G +#define SP_CARET (SP_SYMBOL<<8) | SP_H +#define SP_MINUS (SP_SYMBOL<<8) | SP_J +#define SP_PLUS (SP_SYMBOL<<8) | SP_K +#define SP_EQUAL (SP_SYMBOL<<8) | SP_L +#define SP_COLON (SP_SYMBOL<<8) | SP_Z +#define SP_POUND (SP_SYMBOL<<8) | SP_X +#define SP_QUEST (SP_SYMBOL<<8) | SP_C +#define SP_SLASH (SP_SYMBOL<<8) | SP_V +#define SP_STAR (SP_SYMBOL<<8) | SP_B +#define SP_COMMA (SP_SYMBOL<<8) | SP_N +#define SP_DOT (SP_SYMBOL<<8) | SP_M + +#define SP_EXTEND (SP_CAPS<<8) | SP_SYMBOL +#define SP_EDIT (SP_CAPS<<8) | SP_1 +#define SP_CPSLOCK (SP_CAPS<<8) | SP_2 +#define SP_TRUE (SP_CAPS<<8) | SP_3 +#define SP_INVERSE (SP_CAPS<<8) | SP_4 +#define SP_LEFT (SP_CAPS<<8) | SP_5 +#define SP_DOWN (SP_CAPS<<8) | SP_6 +#define SP_UP (SP_CAPS<<8) | SP_7 +#define SP_RIGHT (SP_CAPS<<8) | SP_8 +#define SP_GRAPH (SP_CAPS<<8) | SP_9 +#define SP_DELETE (SP_CAPS<<8) | SP_0 +#define SP_BREAK (SP_CAPS<<8) | SP_SPACE + +// END of Spectrum keys definitions + +// Definitions for additional signals generated by the keyboard core +// AAADDDDD AAADDDDD MRN JJJJJ MMM XXXXX +#define MODIFIER1 0x20 +#define MODIFIER2 0x40 +#define MODIFIER3 0x80 + +#define MRESET 0x80 +#define URESET 0x40 +#define NMI 0x20 + +#define JOYUP 0x10 +#define JOYDOWN 0x08 +#define JOYLEFT 0x04 +#define JOYRIGHT 0x02 +#define JOYFIRE 0x01 + +#define USER1 0x10 +#define USER2 0x08 +#define USER3 0x04 +#define USER4 0x02 +#define USER5 0x01 +// End of additional signals + +// A key can be pressed with up to three key modifiers +// which generates 8 combinations for each key +#define EXT 0x100 +#define MD1 0x200 +#define MD2 0x400 +#define MD3 0x800 + +#define MAP(pc,sp,rj,mu) { \ + rom[(pc)*4] = (((sp)>>8)&0xFF); \ + rom[(pc)*4+1] = (((sp))&0xFF); \ + rom[(pc)*4+2] = (rj); \ + rom[(pc)*4+3] = (mu); \ + } + +#define MAPANY(pc,sp,rj,mu) { \ + MAP(pc,sp,rj,mu); \ + MAP(MD1|pc,sp,rj,mu); \ + MAP(MD2|pc,sp,rj,mu); \ + MAP(MD3|pc,sp,rj,mu); \ + MAP(MD1|MD2|pc,sp,rj,mu); \ + MAP(MD1|MD3|pc,sp,rj,mu); \ + MAP(MD2|MD3|pc,sp,rj,mu); \ + MAP(MD1|MD2|MD3|pc,sp,rj,mu); \ + } + +#define CLEANMAP { \ + int i; \ + for (i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \ + rom[i] = 0; \ + } +#define SAVEMAPHEX(name) { \ + FILE *f; \ + int i; \ + f=fopen(name,"w"); \ + for(i=0;i<(sizeof(rom)/sizeof(rom[0]));i++) \ + fprintf(f,"%.2X\n",rom[i]); \ + fclose(f); \ + } + +#define SAVEMAPBIN(name) { \ + FILE *f; \ + int i; \ + f=fopen(name,"wb"); \ + fwrite (rom, 1, sizeof(rom), f); \ + fclose(f); \ + } + +// --------------- YOU MAY CUSTOMIZE FROM HERE ------------------------ + +// Scan code 2 list. First, non localized keys +#define PC_A 0x1C +#define PC_B 0x32 +#define PC_C 0x21 +#define PC_D 0x23 +#define PC_E 0x24 +#define PC_F 0x2B +#define PC_G 0x34 +#define PC_H 0x33 +#define PC_I 0x43 +#define PC_J 0x3B +#define PC_K 0x42 +#define PC_L 0x4B +#define PC_M 0x3A +#define PC_N 0x31 +#define PC_O 0x44 +#define PC_P 0x4D +#define PC_Q 0x15 +#define PC_R 0x2D +#define PC_S 0x1B +#define PC_T 0x2C +#define PC_U 0x3C +#define PC_V 0x2A +#define PC_W 0x1D +#define PC_X 0x22 +#define PC_Y 0x35 +#define PC_Z 0x1A + +#define PC_0 0x45 // also ) +#define PC_1 0x16 // also ! +#define PC_2 0x1E // also @ +#define PC_3 0x26 // also # +#define PC_4 0x25 // also $ +#define PC_5 0x2E // also % +#define PC_6 0x36 // also ^ +#define PC_7 0x3D // also & +#define PC_8 0x3E // also * +#define PC_9 0x46 // also ( + +#define PC_F1 0x05 +#define PC_F2 0x06 +#define PC_F3 0x04 +#define PC_F4 0x0C +#define PC_F5 0x03 +#define PC_F6 0x0B +#define PC_F7 0x83 +#define PC_F8 0x0A +#define PC_F9 0x01 +#define PC_F10 0x09 +#define PC_F11 0x78 +#define PC_F12 0x07 + +#define PC_ESC 0x76 +#define PC_SPACE 0x29 +#define PC_LCTRL 0x14 +#define PC_RCTRL 0x14 | EXT +#define PC_LSHIFT 0x12 +#define PC_RSHIFT 0x59 +#define PC_LALT 0x11 +#define PC_RALT 0x11 | EXT +#define PC_LWIN 0x1F | EXT +#define PC_RWIN 0x27 | EXT +#define PC_APPS 0x2F | EXT + +#define PC_TAB 0x0D +#define PC_CPSLOCK 0x58 +#define PC_SCRLOCK 0x7E + +#define PC_INSERT 0x70 | EXT +#define PC_DELETE 0x71 | EXT +#define PC_HOME 0x6C | EXT +#define PC_END 0x69 | EXT +#define PC_PGUP 0x7D | EXT +#define PC_PGDOWN 0x7A | EXT +#define PC_BKSPACE 0x66 +#define PC_ENTER 0x5A +#define PC_UP 0x75 | EXT +#define PC_DOWN 0x72 | EXT +#define PC_LEFT 0x6B | EXT +#define PC_RIGHT 0x74 | EXT + +#define PC_NUMLOCK 0x77 +#define PC_KP_DIVIS 0x4A | EXT +#define PC_KP_MULT 0x7C +#define PC_KP_MINUS 0x7B +#define PC_KP_PLUS 0x79 +#define PC_KP_ENTER 0x5A | EXT +#define PC_KP_DOT 0x71 +#define PC_KP_0 0x70 +#define PC_KP_1 0x69 +#define PC_KP_2 0x72 +#define PC_KP_3 0x7A +#define PC_KP_4 0x6B +#define PC_KP_5 0x73 +#define PC_KP_6 0x74 +#define PC_KP_7 0x6C +#define PC_KP_8 0x75 +#define PC_KP_9 0x7D + +// Localized keyboards usually start to differenciate from here + +// Localized keyboard US +#define PC_GRAVEAC 0x0E // also ~ +#define PC_MINUS 0x4E // also _ +#define PC_EQUAL 0x55 // also + +#define PC_BRAOPEN 0x54 // also { +#define PC_BRACLOS 0x5B // also } +#define PC_BACKSLA 0x5D // also | +#define PC_SEMICOL 0x4C // also : +#define PC_APOSTRO 0x52 // also " +#define PC_COMMA 0x41 // also < +#define PC_DOT 0x49 // also > +#define PC_SLASH 0x4A // also ? + + +int main() +{ + BYTE rom[16384]; + + CLEANMAP; + + MAPANY(PC_LSHIFT,0,0,MODIFIER1); // MD1 is SHIFT + MAPANY(PC_RSHIFT,0,0,MODIFIER1); // MD1 is SHIFT + MAPANY(PC_LCTRL,0,0,MODIFIER2); // MD2 is CTRL + MAPANY(PC_RCTRL,0,0,MODIFIER2); // MD2 is CTRL + MAPANY(PC_LALT,0,JOYFIRE,MODIFIER3); // MD3 is ALT. Also is FIRE for keyboard joystick + MAPANY(PC_RALT,0,JOYFIRE,MODIFIER3); // MD3 is ALT. Also is FIRE for keyboard joystick + + MAPANY(PC_LWIN,SP_CAPS,0,0); // CAPS SHIFT + MAPANY(PC_RWIN,SP_SYMBOL,0,0); // SYMBOL SHIFT + + // Basic mapping: each key from PC is mapped to a key in the Spectrum + MAP(PC_1,SP_1,0,0); + MAP(PC_2,SP_2,0,0); + MAP(PC_3,SP_3,0,0); + MAP(PC_4,SP_4,0,0); + MAP(PC_5,SP_5,0,0); + MAP(PC_6,SP_6,0,0); + MAP(PC_7,SP_7,0,0); + MAP(PC_8,SP_8,0,0); + MAP(PC_9,SP_9,0,0); + MAP(PC_0,SP_0,0,0); + + MAP(PC_Q,SP_Q,0,0); + MAP(PC_W,SP_W,0,0); + MAP(PC_E,SP_E,0,0); + MAP(PC_R,SP_R,0,0); + MAP(PC_T,SP_T,0,0); + MAP(PC_Y,SP_Y,0,0); + MAP(PC_U,SP_U,0,0); + MAP(PC_I,SP_I,0,0); + MAP(PC_O,SP_O,0,0); + MAP(PC_P,SP_P,0,0); + MAP(PC_A,SP_A,0,0); + MAP(PC_S,SP_S,0,0); + MAP(PC_D,SP_D,0,0); + MAP(PC_F,SP_F,0,0); + MAP(PC_G,SP_G,0,0); + MAP(PC_H,SP_H,0,0); + MAP(PC_J,SP_J,0,0); + MAP(PC_K,SP_K,0,0); + MAP(PC_L,SP_L,0,0); + MAP(PC_Z,SP_Z,0,0); + MAP(PC_X,SP_X,0,0); + MAP(PC_C,SP_C,0,0); + MAP(PC_V,SP_V,0,0); + MAP(PC_B,SP_B,0,0); + MAP(PC_N,SP_N,0,0); + MAP(PC_M,SP_M,0,0); + + // a letter key with shift (MD1) is like pressing CAPS SHIFT + letter + MAP(MD1|PC_Q,SP_CAPS<<8|SP_Q,0,0); + MAP(MD1|PC_W,SP_CAPS<<8|SP_W,0,0); + MAP(MD1|PC_E,SP_CAPS<<8|SP_E,0,0); + MAP(MD1|PC_R,SP_CAPS<<8|SP_R,0,0); + MAP(MD1|PC_T,SP_CAPS<<8|SP_T,0,0); + MAP(MD1|PC_Y,SP_CAPS<<8|SP_Y,0,0); + MAP(MD1|PC_U,SP_CAPS<<8|SP_U,0,0); + MAP(MD1|PC_I,SP_CAPS<<8|SP_I,0,0); + MAP(MD1|PC_O,SP_CAPS<<8|SP_O,0,0); + MAP(MD1|PC_P,SP_CAPS<<8|SP_P,0,0); + MAP(MD1|PC_A,SP_CAPS<<8|SP_A,0,0); + MAP(MD1|PC_S,SP_CAPS<<8|SP_S,0,0); + MAP(MD1|PC_D,SP_CAPS<<8|SP_D,0,0); + MAP(MD1|PC_F,SP_CAPS<<8|SP_F,0,0); + MAP(MD1|PC_G,SP_CAPS<<8|SP_G,0,0); + MAP(MD1|PC_H,SP_CAPS<<8|SP_H,0,0); + MAP(MD1|PC_J,SP_CAPS<<8|SP_J,0,0); + MAP(MD1|PC_K,SP_CAPS<<8|SP_K,0,0); + MAP(MD1|PC_L,SP_CAPS<<8|SP_L,0,0); + MAP(MD1|PC_Z,SP_CAPS<<8|SP_Z,0,0); + MAP(MD1|PC_X,SP_CAPS<<8|SP_X,0,0); + MAP(MD1|PC_C,SP_CAPS<<8|SP_C,0,0); + MAP(MD1|PC_V,SP_CAPS<<8|SP_V,0,0); + MAP(MD1|PC_B,SP_CAPS<<8|SP_B,0,0); + MAP(MD1|PC_N,SP_CAPS<<8|SP_N,0,0); + MAP(MD1|PC_M,SP_CAPS<<8|SP_M,0,0); + + MAPANY(PC_SPACE,SP_SPACE,0,0); + MAPANY(PC_ENTER,SP_ENTER,0,0); + + //Complex mapping. This is for the US keyboard although many + //combos can be used with any other PC keyboard + MAPANY(PC_ESC,SP_BREAK,0,0); + MAPANY(PC_CPSLOCK,SP_CPSLOCK,0,0); + MAPANY(PC_TAB,SP_EXTEND,0,0); + MAP(PC_BKSPACE,SP_DELETE,0,0); + MAPANY(PC_UP,SP_UP,0,0); + MAPANY(PC_DOWN,SP_DOWN,0,0); + MAPANY(PC_LEFT,SP_LEFT,0,0); + MAPANY(PC_RIGHT,SP_RIGHT,0,0); + MAPANY(PC_F2,SP_EDIT,0,0); + + MAP(PC_F5|MD2|MD3,0,NMI,0); // Ctrl-Alt-F5 for NMI + MAP(PC_F10,SP_GRAPH,0,0); // F10 habilita el modo gráfico. Esto es para Antonio, para la BIOS + MAP(PC_DELETE|MD2|MD3,0,URESET,0); // + MAP(PC_KP_DOT|MD2|MD3,0,URESET,0); // Ctrl-Alt-Del for user reset + MAP(PC_BKSPACE|MD2|MD3,0,MRESET,0); // Ctrl-Alt-BkSpace for master reset + + //keypad + MAPANY(PC_KP_DIVIS,SP_SLASH,0,0); + MAPANY(PC_KP_MULT,SP_STAR,0,0); + MAPANY(PC_KP_MINUS,SP_MINUS,0,0); + MAPANY(PC_KP_PLUS,SP_PLUS,0,0); + MAPANY(PC_KP_ENTER,SP_ENTER,0,0); + + // a 8-way keyboard joystick on the keypad + MAPANY(PC_KP_7,0,JOYUP|JOYLEFT,0); + MAPANY(PC_KP_8,0,JOYUP,0); + MAPANY(PC_KP_9,0,JOYUP|JOYRIGHT,0); + MAPANY(PC_KP_4,0,JOYLEFT,0); + MAPANY(PC_KP_5,0,JOYDOWN,0); + MAPANY(PC_KP_6,0,JOYRIGHT,0); + MAPANY(PC_KP_1,0,JOYDOWN|JOYLEFT,0); + MAPANY(PC_KP_2,0,JOYDOWN,0); + MAPANY(PC_KP_3,0,JOYDOWN|JOYRIGHT,0); + + //Some keys and shift+key mappings for the US keyboard + MAP(MD1|PC_1,SP_BANG,0,0); + MAP(MD1|PC_2,SP_AT,0,0); + MAP(MD1|PC_3,SP_HASH,0,0); + MAP(MD1|PC_4,SP_DOLLAR,0,0); + MAP(MD1|PC_5,SP_PERCEN,0,0); + MAP(MD1|PC_6,SP_CARET,0,0); + MAP(MD1|PC_7,SP_AMP,0,0); + MAP(MD1|PC_8,SP_STAR,0,0); + MAP(MD1|PC_9,SP_PAROPEN,0,0); + MAP(MD1|PC_0,SP_PARCLOS,0,0); + MAP(PC_MINUS,SP_MINUS,0,0); + MAP(MD1|PC_MINUS,SP_UNDERSC,0,0); + MAP(PC_EQUAL,SP_EQUAL,0,0); + MAP(MD1|PC_EQUAL,SP_PLUS,0,0); + MAP(PC_BRAOPEN,SP_BRAOPEN,0,0); + MAP(MD1|PC_BRAOPEN,SP_CUROPEN,0,0); + MAP(PC_BRACLOS,SP_BRACLOS,0,0); + MAP(MD1|PC_BRACLOS,SP_BRACLOS,0,0); + MAP(PC_BACKSLA,SP_BACKSLA,0,0); + MAP(MD1|PC_BACKSLA,SP_PIPE,0,0); + MAP(PC_APOSTRO,SP_APOSTRO,0,0); + MAP(MD1|PC_APOSTRO,SP_QUOTE,0,0); + MAP(PC_COMMA,SP_COMMA,0,0); + MAP(MD1|PC_COMMA,SP_LESS,0,0); + MAP(PC_DOT,SP_DOT,0,0); + MAP(MD1|PC_DOT,SP_GREATER,0,0); + MAP(PC_SLASH,SP_SLASH,0,0); + MAP(MD1|PC_SLASH,SP_QUEST,0,0); + + // End of mapping. Save .HEX file for Verilog + //SAVEMAPHEX("keyb_us_hex.txt"); + // And map file for loading from ESXDOS + SAVEMAPBIN("keymaps\\US"); +} diff --git a/cores/Spectrum/joystick_protocols.v b/cores/Spectrum/joystick_protocols.v new file mode 100644 index 0000000..7c7f853 --- /dev/null +++ b/cores/Spectrum/joystick_protocols.v @@ -0,0 +1,137 @@ +`timescale 1ns / 1ps +`default_nettype none + +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 15:52:26 06/07/2015 +// Design Name: +// Module Name: joystick_protocols +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module joystick_protocols( + input wire clk, + //-- cpu interface + input wire [15:0] a, + input wire iorq_n, + input wire rd_n, + input wire [7:0] din, + output reg [7:0] dout, + output reg oe_n, + //-- interface with ZXUNO reg bank + input wire [7:0] zxuno_addr, + input wire zxuno_regrd, + input wire zxuno_regwr, + //-- actual joystick and keyboard signals + input wire [4:0] kbdjoy_in, + input wire [4:0] db9joy_in, + input wire [4:0] kbdcol_in, + output reg [4:0] kbdcol_out, + input wire vertical_retrace_int_n // this is used as base clock for autofire + ); + + parameter + JOYCONFADDR = 8'h06, + KEMPSTONADDR = 8'h1F, + SINCLAIRP1ADDR = 12, + SINCLAIRP2ADDR = 11, + FULLERADDR = 8'h7F, + DISABLED = 3'h0, + KEMPSTON = 3'h1, + SINCLAIRP1 = 3'h2, + SINCLAIRP2 = 3'h3, + CURSOR = 3'h4, + FULLER = 3'h5; + + // Input format: FUDLR . 0=pressed, 1=released + reg db9joyup = 1'b0; + reg db9joydown = 1'b0; + reg db9joyleft = 1'b0; + reg db9joyright = 1'b0; + reg db9joyfire = 1'b0; + reg kbdjoyup = 1'b0; + reg kbdjoydown = 1'b0; + reg kbdjoyleft = 1'b0; + reg kbdjoyright = 1'b0; + reg kbdjoyfire = 1'b0; + always @(posedge clk) begin + {db9joyfire,db9joyup,db9joydown,db9joyleft,db9joyright} <= ~db9joy_in; + {kbdjoyfire,kbdjoyup,kbdjoydown,kbdjoyleft,kbdjoyright} <= kbdjoy_in; + end + + // Update JOYCONF from CPU + reg [7:0] joyconf = {1'b0,SINCLAIRP1, 1'b0,KEMPSTON}; + always @(posedge clk) begin + if (zxuno_addr==JOYCONFADDR && zxuno_regwr==1'b1) + joyconf <= din; + end + + // Autofire stuff + reg [2:0] cont_autofire = 3'b000; + reg [3:0] edge_detect = 4'b0000; + wire autofire = cont_autofire[2]; + always @(posedge clk) begin + edge_detect <= {edge_detect[2:0], vertical_retrace_int_n}; + if (edge_detect == 4'b0011) + cont_autofire <= cont_autofire + 1; // count only on raising edge of vertical retrace int + end + wire kbdjoyfire_processed = (joyconf[3]==1'b0)? kbdjoyfire : kbdjoyfire & autofire; + wire db9joyfire_processed = (joyconf[7]==1'b0)? db9joyfire : db9joyfire & autofire; + + always @* begin + oe_n = 1'b1; + dout = 8'hZZ; + kbdcol_out = kbdcol_in; + if (zxuno_addr==JOYCONFADDR && zxuno_regrd==1'b1) begin + oe_n = 1'b0; + dout = joyconf; + end + else if (iorq_n == 1'b0 && a[7:0]==KEMPSTONADDR && rd_n==1'b0) begin + dout = 8'h00; + oe_n = 1'b0; + if (joyconf[2:0]==KEMPSTON) + dout = dout | {3'b000, kbdjoyfire_processed, kbdjoyup, kbdjoydown, kbdjoyleft, kbdjoyright}; + if (joyconf[6:4]==KEMPSTON) + dout = dout | {3'b000, db9joyfire_processed, db9joyup, db9joydown, db9joyleft, db9joyright}; + end + else if (iorq_n == 1'b0 && a[7:0]==FULLERADDR && rd_n==1'b0) begin + dout = 8'hFF; + oe_n = 1'b0; + if (joyconf[2:0]==FULLER) + dout = dout & {~kbdjoyfire_processed, 3'b111, ~kbdjoyright, ~kbdjoyleft, ~kbdjoydown, ~kbdjoyup}; + if (joyconf[6:4]==FULLER) + dout = dout & {~db9joyfire_processed, 3'b111, ~db9joyright, ~db9joyleft, ~db9joydown, ~db9joyup}; + end + else if (iorq_n==1'b0 && a[SINCLAIRP1ADDR]==1'b0 && a[0]==1'b0 && rd_n==1'b0) begin + if (joyconf[2:0]==SINCLAIRP1) + kbdcol_out = kbdcol_out & {~kbdjoyleft,~kbdjoyright,~kbdjoydown,~kbdjoyup,~kbdjoyfire_processed}; + if (joyconf[6:4]==SINCLAIRP1) + kbdcol_out = kbdcol_out & {~db9joyleft,~db9joyright,~db9joydown,~db9joyup,~db9joyfire_processed}; + if (joyconf[2:0]==CURSOR) + kbdcol_out = kbdcol_out & {~kbdjoydown,~kbdjoyup,~kbdjoyright,1'b1,~kbdjoyfire_processed}; + if (joyconf[6:4]==CURSOR) + kbdcol_out = kbdcol_out & {~db9joydown,~db9joyup,~db9joyright,1'b1,~db9joyfire_processed}; + end + else if (iorq_n==1'b0 && a[SINCLAIRP2ADDR]==1'b0 && a[0]==1'b0 && rd_n==1'b0) begin + if (joyconf[2:0]==SINCLAIRP2) + kbdcol_out = kbdcol_out & {~kbdjoyfire_processed,~kbdjoyup,~kbdjoydown,~kbdjoyright,~kbdjoyleft}; + if (joyconf[6:4]==SINCLAIRP2) + kbdcol_out = kbdcol_out & {~db9joyfire_processed,~db9joyup,~db9joydown,~db9joyright,~db9joyleft}; + if (joyconf[2:0]==CURSOR) + kbdcol_out = kbdcol_out & {~kbdjoyleft,4'b1111}; + if (joyconf[6:4]==CURSOR) + kbdcol_out = kbdcol_out & {~db9joyleft,4'b1111}; + end + end +endmodule diff --git a/cores/Spectrum/keyb_es_hex.txt b/cores/Spectrum/keyb_es_hex.txt new file mode 100644 index 0000000..1e3405d --- /dev/null +++ b/cores/Spectrum/keyb_es_hex.txt @@ -0,0 +1,16384 @@ +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +82 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +E2 +24 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +41 +00 +00 +00 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +02 +00 +00 +00 +22 +00 +00 +00 +21 +00 +00 +00 +42 +00 +00 +00 +62 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +04 +00 +00 +00 +24 +00 +00 +00 +44 +00 +00 +00 +68 +00 +00 +00 +64 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +10 +00 +00 +00 +28 +00 +00 +00 +50 +00 +00 +00 +48 +00 +00 +00 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E8 +00 +00 +00 +F0 +00 +00 +00 +D0 +00 +00 +00 +30 +00 +00 +00 +B0 +00 +00 +00 +90 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E4 +00 +00 +00 +C8 +00 +00 +00 +A8 +00 +00 +00 +88 +00 +00 +00 +84 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +E8 +00 +00 +00 +C4 +00 +00 +00 +A4 +00 +00 +00 +A2 +00 +00 +00 +81 +00 +00 +00 +82 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +E4 +00 +00 +E2 +C8 +00 +00 +00 +C2 +00 +00 +E2 +21 +00 +00 +00 +A1 +00 +00 +E2 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +28 +00 +00 +00 +00 +00 +00 +E2 +04 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +E2 +C4 +00 +00 +00 +00 +00 +00 +E2 +30 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +48 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +81 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +E2 +24 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +01 +41 +00 +00 +E2 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +02 +00 +00 +01 +22 +00 +00 +01 +21 +00 +00 +01 +42 +00 +00 +E2 +A1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +08 +00 +00 +01 +04 +00 +00 +01 +24 +00 +00 +01 +44 +00 +00 +E2 +68 +00 +00 +E2 +64 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +01 +10 +00 +00 +01 +28 +00 +00 +01 +50 +00 +00 +01 +48 +00 +00 +E2 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E8 +00 +00 +01 +F0 +00 +00 +01 +D0 +00 +00 +01 +30 +00 +00 +01 +B0 +00 +00 +E2 +90 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E4 +00 +00 +01 +C8 +00 +00 +01 +A8 +00 +00 +E2 +10 +00 +00 +E2 +84 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +A2 +00 +00 +01 +C4 +00 +00 +01 +A4 +00 +00 +01 +A2 +00 +00 +E2 +C2 +00 +00 +E2 +82 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +02 +00 +00 +E2 +81 +00 +00 +01 +C2 +00 +00 +00 +00 +00 +00 +01 +A1 +00 +00 +E2 +08 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +28 +00 +00 +00 +00 +00 +00 +E2 +D0 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +E2 +F0 +00 +00 +00 +00 +00 +00 +E2 +A1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +41 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +44 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +42 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +42 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +42 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +61 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +62 +00 +00 +00 +00 +00 +20 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +42 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0C +00 +00 +00 +00 +00 +00 +00 +04 +00 +00 +00 +14 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +08 +00 +00 +00 +08 +00 +00 +00 +02 +00 +00 +00 +10 +00 +01 +E1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +C4 +00 +00 +00 +00 +0A +00 +E2 +C8 +00 +00 +E2 +F0 +00 +00 +00 +00 +12 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +80 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +E2 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C1 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +90 +00 +00 +00 +00 +00 +00 +01 +84 +00 +00 +01 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 diff --git a/cores/Spectrum/keymaps/ES b/cores/Spectrum/keymaps/ES new file mode 100644 index 0000000..e4c3710 Binary files /dev/null and b/cores/Spectrum/keymaps/ES differ diff --git a/cores/Spectrum/keymaps/US b/cores/Spectrum/keymaps/US new file mode 100644 index 0000000..586ca77 Binary files /dev/null and b/cores/Spectrum/keymaps/US differ diff --git a/cores/Spectrum/ps2_keyb.v b/cores/Spectrum/ps2_keyb.v new file mode 100644 index 0000000..8f01bc7 --- /dev/null +++ b/cores/Spectrum/ps2_keyb.v @@ -0,0 +1,131 @@ +`timescale 1ns / 1ps +`default_nettype none + +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 15:18:53 06/03/2015 +// Design Name: +// Module Name: ps2_keyb +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module ps2_keyb( + input wire clk, + inout wire clkps2, + inout wire dataps2, + //--------------------------------- + input wire [7:0] rows, + output wire [4:0] cols, + output wire [4:0] joy, + output wire rst_out_n, + output wire nmi_out_n, + output wire mrst_out_n, + output wire [4:0] user_toggles, + //--------------------------------- + input wire [7:0] zxuno_addr, + input wire zxuno_regrd, + input wire zxuno_regwr, + input wire regaddr_changed, + input wire [7:0] din, + output wire [7:0] keymap_dout, + output wire oe_n_keymap, + output wire [7:0] scancode_dout, + output wire oe_n_scancode, + output reg [7:0] kbstatus_dout, + output wire oe_n_kbstatus + ); + + parameter SCANCODE = 8'h04; + parameter KBSTATUS = 8'h05; + parameter KEYMAP = 8'h07; + + wire master_reset, user_reset, user_nmi; + assign mrst_out_n = ~master_reset; + assign rst_out_n = ~user_reset; + assign nmi_out_n = ~user_nmi; + + assign oe_n_keymap = ~(zxuno_addr == KEYMAP && zxuno_regrd == 1'b1); + assign oe_n_scancode = ~(zxuno_addr == SCANCODE && zxuno_regrd == 1'b1); + assign oe_n_kbstatus = ~(zxuno_addr == KBSTATUS && zxuno_regrd == 1'b1); + + wire [7:0] kbcode; + wire ps2busy; + wire kberror; + wire nueva_tecla; + wire extended; + wire released; + assign scancode_dout = kbcode; + + /* + | BSY | x | x | x | ERR | RLS | EXT | PEN | + */ + reg reading_kbstatus = 1'b0; + always @(posedge clk) begin + kbstatus_dout[7:1] <= {ps2busy, 3'b000, kberror, released, extended}; + if (nueva_tecla == 1'b1) + kbstatus_dout[0] <= 1'b1; + if (oe_n_kbstatus == 1'b0) + reading_kbstatus <= 1'b1; + else if (reading_kbstatus == 1'b1) begin + kbstatus_dout[0] <= 1'b0; + reading_kbstatus <= 1'b0; + end + end + + ps2_port lectura_de_teclado ( + .clk(clk), + .enable_rcv(~ps2busy), + .ps2clk_ext(clkps2), + .ps2data_ext(dataps2), + .kb_interrupt(nueva_tecla), + .scancode(kbcode), + .released(released), + .extended(extended) + ); + + scancode_to_speccy traductor ( + .clk(clk), + .rst(1'b0), + .scan_received(nueva_tecla), + .scan(kbcode), + .extended(extended), + .released(released), + .sp_row(rows), + .sp_col(cols), + .joyup(joy[3]), + .joydown(joy[2]), + .joyleft(joy[1]), + .joyright(joy[0]), + .joyfire(joy[4]), + .master_reset(master_reset), + .user_reset(user_reset), + .user_nmi(user_nmi), + .user_toggles(user_toggles), + .din(din), + .dout(keymap_dout), + .cpuwrite(zxuno_addr == KEYMAP && zxuno_regwr == 1'b1), + .cpuread(zxuno_addr == KEYMAP && zxuno_regrd == 1'b1), + .rewind(regaddr_changed == 1'b1 && zxuno_addr == KEYMAP) + ); + + ps2_host_to_kb escritura_a_teclado ( + .clk(clk), + .ps2clk_ext(clkps2), + .ps2data_ext(dataps2), + .data(din), + .dataload(zxuno_addr == SCANCODE && zxuno_regwr== 1'b1), + .ps2busy(ps2busy), + .ps2error(kberror) + ); +endmodule diff --git a/cores/Spectrum/ps2_port.v b/cores/Spectrum/ps2_port.v new file mode 100644 index 0000000..31eb055 --- /dev/null +++ b/cores/Spectrum/ps2_port.v @@ -0,0 +1,242 @@ +`timescale 1ns / 1ps +`default_nettype none + +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 20:16:31 12/26/2014 +// Design Name: +// Module Name: ps2_port +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module ps2_port ( + input wire clk, // se recomienda 1 MHz <= clk <= 600 MHz + input wire enable_rcv, // habilitar la maquina de estados de recepcion + input wire ps2clk_ext, + input wire ps2data_ext, + output wire kb_interrupt, // a 1 durante 1 clk para indicar nueva tecla recibida + output reg [7:0] scancode, // make o breakcode de la tecla + output wire released, // soltada=1, pulsada=0 + output wire extended // extendida=1, no extendida=0 + ); + + `define RCVSTART 2'b00 + `define RCVDATA 2'b01 + `define RCVPARITY 2'b10 + `define RCVSTOP 2'b11 + + reg [7:0] key = 8'h00; + + // Fase de sincronizacion de señales externas con el reloj del sistema + reg [1:0] ps2clk_synchr; + reg [1:0] ps2dat_synchr; + wire ps2clk = ps2clk_synchr[1]; + wire ps2data = ps2dat_synchr[1]; + always @(posedge clk) begin + ps2clk_synchr[0] <= ps2clk_ext; + ps2clk_synchr[1] <= ps2clk_synchr[0]; + ps2dat_synchr[0] <= ps2data_ext; + ps2dat_synchr[1] <= ps2dat_synchr[0]; + end + + // De-glitcher. Sólo detecto flanco de bajada + reg [15:0] negedgedetect = 16'h0000; + always @(posedge clk) begin + negedgedetect <= {negedgedetect[14:0], ps2clk}; + end + wire ps2clkedge = (negedgedetect == 16'hFF00)? 1'b1 : 1'b0; + + // Paridad instantánea de los bits recibidos + wire paritycalculated = ^key; + + // Contador de time-out. Al llegar a 65536 ciclos sin que ocurra + // un flanco de bajada en PS2CLK, volvemos al estado inicial + reg [15:0] timeoutcnt = 16'h0000; + + reg [1:0] state = `RCVSTART; + reg [1:0] regextended = 2'b00; + reg [1:0] regreleased = 2'b00; + reg rkb_interrupt = 1'b0; + assign released = regreleased[1]; + assign extended = regextended[1]; + assign kb_interrupt = rkb_interrupt; + + always @(posedge clk) begin + if (rkb_interrupt == 1'b1) begin + rkb_interrupt <= 1'b0; + end + if (ps2clkedge && enable_rcv) begin + timeoutcnt <= 16'h0000; + if (state == `RCVSTART && ps2data == 1'b0) begin + state <= `RCVDATA; + key <= 8'h80; + //rkb_interrupt <= 1'b0; + end + else if (state == `RCVDATA) begin + key <= {ps2data, key[7:1]}; + if (key[0] == 1'b1) begin + state <= `RCVPARITY; + end + end + else if (state == `RCVPARITY) begin + if (ps2data^paritycalculated == 1'b1) begin + state <= `RCVSTOP; + end + else begin + state <= `RCVSTART; + end + end + else if (state == `RCVSTOP) begin + state <= `RCVSTART; + if (ps2data == 1'b1) begin + scancode <= key; + if (key == 8'hE0) begin + regextended <= 2'b01; + end + else if (key == 8'hF0) begin + regreleased <= 2'b01; + end + else begin + regextended <= {regextended[0], 1'b0}; + regreleased <= {regreleased[0], 1'b0}; + rkb_interrupt <= 1'b1; + end + end + end + end + else begin + timeoutcnt <= timeoutcnt + 1; + if (timeoutcnt == 16'hFFFF) begin + state <= `RCVSTART; + end + end + end +endmodule + + +module ps2_host_to_kb ( + input wire clk, // se recomienda 1 MHz <= clk <= 600 MHz + inout wire ps2clk_ext, + inout wire ps2data_ext, + input wire [7:0] data, + input wire dataload, + output wire ps2busy, + output wire ps2error + ); + + `define PULLCLKLOW 3'b000 + `define PULLDATALOW 3'b001 + `define SENDDATA 3'b010 + `define SENDPARITY 3'b011 + `define RCVACK 3'b100 + `define RCVIDLE 3'b101 + `define SENDFINISHED 3'b110 + + reg busy = 1'b0; + reg error = 1'b0; + assign ps2busy = busy; + assign ps2error = error; + + // Fase de sincronizacion de señales externas con el reloj del sistema + reg [1:0] ps2clk_synchr; + reg [1:0] ps2dat_synchr; + wire ps2clk = ps2clk_synchr[1]; + wire ps2data_in = ps2dat_synchr[1]; + always @(posedge clk) begin + ps2clk_synchr[0] <= ps2clk_ext; + ps2clk_synchr[1] <= ps2clk_synchr[0]; + ps2dat_synchr[0] <= ps2data_ext; + ps2dat_synchr[1] <= ps2dat_synchr[0]; + end + + // De-glitcher. Sólo detecto flanco de bajada + reg [15:0] edgedetect = 16'h0000; + always @(posedge clk) begin + edgedetect <= {edgedetect[14:0], ps2clk}; + end + wire ps2clknedge = (edgedetect == 16'hF000)? 1'b1 : 1'b0; + wire ps2clkpedge = (edgedetect == 16'h0FFF)? 1'b1 : 1'b0; + + // Contador de time-out. Al llegar a 65536 ciclos sin que ocurra + // un flanco de bajada en PS2CLK, volvemos al estado inicial + reg [15:0] timeoutcnt = 16'h0000; + + reg [2:0] state = `SENDFINISHED; + reg [7:0] shiftreg = 8'h00; + reg [2:0] cntbits = 3'd0; + + // Dato a enviar se guarda en rdata + reg [7:0] rdata = 8'h00; + + // Paridad instantánea de los bits a enviar + wire paritycalculated = ~(^rdata); + + always @(posedge clk) begin + // Carga de rdata desde el exterior + if (dataload) begin + rdata <= data; + busy <= 1'b1; + error <= 1'b0; + timeoutcnt <= 16'h0000; + state <= `PULLCLKLOW; + end + + if (state == `PULLCLKLOW && timeoutcnt >= 16'd40000) begin // 40000 cuentas es poco más de 10ms + state <= `PULLDATALOW; + shiftreg <= rdata; + cntbits <= 3'd0; + timeoutcnt <= 16'h0000; + end + else if (state == `PULLDATALOW && ps2clknedge) begin + state <= `SENDDATA; + timeoutcnt <= 16'h0000; + end + else if (state == `SENDDATA && ps2clknedge) begin + timeoutcnt <= 16'h0000; + shiftreg <= {1'b0, shiftreg[7:1]}; + cntbits <= cntbits + 1; + if (cntbits == 3'd7) + state <= `SENDPARITY; + end + else if (state == `SENDPARITY && ps2clknedge) begin + state <= `RCVIDLE; + timeoutcnt <= 16'h0000; + end + else if (state == `RCVIDLE && ps2clknedge /*&& ps2data_in == 1'b1*/) begin + state <= `RCVACK; + timeoutcnt <= 16'h0000; + end + else if (state == `RCVACK && ps2clknedge /*&& ps2data_in == 1'b0*/) begin + state <= `SENDFINISHED; + timeoutcnt <= 16'h0000; + end + else if (state == `SENDFINISHED) begin + busy <= 1'b0; + timeoutcnt <= 16'h0000; + end + else begin + timeoutcnt <= timeoutcnt + 1; + if (timeoutcnt == 16'hFFFF && state != `SENDFINISHED) begin + error <= 1'b1; + state <= `SENDFINISHED; + end + end + end + assign ps2data_ext = (state == `PULLCLKLOW || state == `PULLDATALOW) ? 1'b0 : + (state == `SENDDATA && shiftreg[0] == 1'b0) ? 1'b0 : + (state == `SENDPARITY && paritycalculated == 1'b0) ? 1'b0 : // si lo que se va a enviar es un 1 + 1'bZ; // no se manda, sino que se pone la línea a alta impedancia + assign ps2clk_ext = (state == `PULLCLKLOW) ? 1'b0 : + 1'bZ; +endmodule diff --git a/cores/Spectrum/ps2k_mcleod.vhd b/cores/Spectrum/ps2k_mcleod.vhd index 368765a..101dcaa 100644 --- a/cores/Spectrum/ps2k_mcleod.vhd +++ b/cores/Spectrum/ps2k_mcleod.vhd @@ -309,6 +309,14 @@ begin when KEY_KP6 => joy(0) <= pressed; -- dato entregado por el joystick: derecha when KEY_KP8 => joy(3) <= pressed; -- dato entregado por el joystick: arriba when KEY_KP5 => joy(2) <= pressed; -- dato entregado por el joystick: abajo + when KEY_KP7 => joy(1) <= pressed; + joy(3) <= pressed; -- dato entregado por el joystick: arriba izquierda + when KEY_KP9 => joy(0) <= pressed; + joy(3) <= pressed; -- dato entregado por el joystick: arriba derecha + when KEY_KP1 => joy(1) <= pressed; + joy(2) <= pressed; -- dato entregado por el joystick: abajo izquierda + when KEY_KP3 => joy(0) <= pressed; + joy(2) <= pressed; -- dato entregado por el joystick: abajo derecha when others=> null; end case; else -- process extended keys diff --git a/cores/Spectrum/rom.v b/cores/Spectrum/rom.v index 38d4599..2ad59db 100644 --- a/cores/Spectrum/rom.v +++ b/cores/Spectrum/rom.v @@ -24,18 +24,16 @@ module rom ( output reg [7:0] dout ); - reg [7:0] mem[0:63]; + reg [7:0] mem[0:127]; integer i; initial begin // usa $readmemb/$readmemh dependiendo del formato del fichero que contenga la ROM - for (i=0;i<64;i=i+1) begin + for (i=0;i<128;i=i+1) begin mem[i] = 8'h00; end $readmemh ("bootloader_hex.txt", mem, 0); - //$readmemb ("rom_48k_bin.txt", mem, 0); - //$readmemh ("testcontenida_hex.txt", mem, 0); end always @(posedge clk) begin - dout <= mem[a[5:0]]; + dout <= mem[a[6:0]]; end endmodule diff --git a/cores/Spectrum/scancode_to_speccy.v b/cores/Spectrum/scancode_to_speccy.v new file mode 100644 index 0000000..78711e4 --- /dev/null +++ b/cores/Spectrum/scancode_to_speccy.v @@ -0,0 +1,267 @@ +`timescale 1ns / 1ps +`default_nettype none +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 17:42:40 06/01/2015 +// Design Name: +// Module Name: scancode_to_speccy +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module scancode_to_speccy ( + input wire clk, // el mismo clk de ps/2 + input wire rst, + input wire scan_received, + input wire [7:0] scan, + input wire extended, + input wire released, + //------------------------ + input wire [7:0] sp_row, + output wire [4:0] sp_col, + output wire user_reset, + output wire master_reset, + output wire user_nmi, + output wire joyup, + output wire joydown, + output wire joyleft, + output wire joyright, + output wire joyfire, + output wire [4:0] user_toggles, + //------------------------ + input wire [7:0] din, + output reg [7:0] dout, + input wire cpuwrite, + input wire cpuread, + input wire rewind + ); + + // las 40 teclas del Spectrum. Se inicializan a "no pulsadas". + reg [4:0] row[0:7]; + initial begin + row[0] = 5'b11111; + row[1] = 5'b11111; + row[2] = 5'b11111; + row[3] = 5'b11111; + row[4] = 5'b11111; + row[5] = 5'b11111; + row[6] = 5'b11111; + row[7] = 5'b11111; + end + + // El gran mapa de teclado y sus registros de acceso + reg [7:0] keymap[0:16383]; // 16K x 8 bits + reg [13:0] addr = 14'h0000; + reg [13:0] cpuaddr = 14'h0000; // Dirección E/S desde la CPU. Se autoincrementa en cada acceso + initial begin + $readmemh ("keyb_es_hex.txt", keymap); + end + + reg [2:0] keyrow1 = 3'h0; + reg [4:0] keycol1 = 5'h00; + reg [2:0] keyrow2 = 3'h0; + reg [4:0] keycol2 = 5'h00; + reg [2:0] keymodifiers = 3'b000; + reg [2:0] signalstate = 3'b000; + reg [4:0] joystate = 5'b00000; + reg [4:0] togglestate = 5'h00; + + reg rmaster_reset = 1'b0, ruser_reset = 1'b0, ruser_nmi = 1'b0; + reg rjoyup = 1'b0, rjoydown = 1'b0, rjoyleft = 1'b0, rjoyright = 1'b0, rjoyfire = 1'b0; + reg [4:0] ruser_toggles = 5'h00; + assign joyup = rjoyup; + assign joydown = rjoydown; + assign joyleft = rjoyleft; + assign joyright = rjoyright; + assign joyfire = rjoyfire; + assign master_reset = rmaster_reset; + assign user_reset = ruser_reset; + assign user_nmi = ruser_nmi; + assign user_toggles = ruser_toggles; + + // Asi funciona la matriz de teclado cuando se piden semifilas + // desde la CPU. + // Un always @* hubiera quedado más claro en la descripción + // pero por algun motivo, el XST no lo ha admitido en este caso + assign sp_col = ((sp_row[0] == 1'b0)? row[0] : 5'b11111) & + ((sp_row[1] == 1'b0)? row[1] : 5'b11111) & + ((sp_row[2] == 1'b0)? row[2] : 5'b11111) & + ((sp_row[3] == 1'b0)? row[3] : 5'b11111) & + ((sp_row[4] == 1'b0)? row[4] : 5'b11111) & + ((sp_row[5] == 1'b0)? row[5] : 5'b11111) & + ((sp_row[6] == 1'b0)? row[6] : 5'b11111) & + ((sp_row[7] == 1'b0)? row[7] : 5'b11111); + + reg [2:0] modifiers = 3'b000; + reg [3:0] keycount = 4'b0000; + + parameter + CLEANMATRIX = 4'd0, + IDLE = 4'd1, + ADDR0PUT = 4'd2, + ADDR1PUT = 4'd3, + ADDR2PUT = 4'd4, + ADDR3PUT = 4'd5, + TRANSLATE1 = 4'd6, + TRANSLATE2 = 4'd7, + TRANSLATE3 = 4'd8, + CPUTIME = 4'd9, + CPUREAD = 4'd10, + CPUWRITE = 4'd11, + CPUINCADD = 4'd12, + UPDCOUNTERS1= 4'd13, + UPDCOUNTERS2= 4'd14; + + reg [3:0] state = CLEANMATRIX; + reg key_is_pending = 1'b0; + + always @(posedge clk) begin + if (scan_received == 1'b1) + key_is_pending <= 1'b1; + if (rst == 1'b1) + state <= CLEANMATRIX; + else if (state == CLEANMATRIX) begin + modifiers <= 3'b000; + keycount <= 4'b0000; + row[0] <= 5'b11111; + row[1] <= 5'b11111; + row[2] <= 5'b11111; + row[3] <= 5'b11111; + row[4] <= 5'b11111; + row[5] <= 5'b11111; + row[6] <= 5'b11111; + row[7] <= 5'b11111; + state <= IDLE; + end + else if (state == IDLE) begin + if (key_is_pending == 1'b1) begin + addr <= {modifiers, extended, scan, 2'b00}; // 1 scan tiene 8 bits + 1 bit para indicar scan extendido + 3 bits para el modificador usado + state <= ADDR0PUT; + key_is_pending <= 1'b0; + end + else if (cpuread == 1'b1 || cpuwrite == 1'b1 || rewind == 1'b1) + state <= CPUTIME; + end + else if (state == ADDR0PUT) begin + {keyrow1,keycol1} <= keymap[addr]; + addr <= {modifiers, extended, scan, 2'b01}; + state <= ADDR1PUT; + end + else if (state == ADDR1PUT) begin + {keyrow2,keycol2} <= keymap[addr]; + addr <= {modifiers, extended, scan, 2'b10}; + state <= ADDR2PUT; + end + else if (state == ADDR2PUT) begin + {signalstate,joystate} <= keymap[addr]; + addr <= {modifiers, extended, scan, 2'b11}; + state <= ADDR3PUT; + end + else if (state == ADDR3PUT) begin + {keymodifiers,togglestate} <= keymap[addr]; + state <= TRANSLATE1; + end + else if (state == TRANSLATE1) begin + // Actualiza las 8 semifilas del teclado con la primera tecla + if (~released) begin + row[keyrow1] <= row[keyrow1] & ~keycol1; + end + else begin + row[keyrow1] <= row[keyrow1] | keycol1; + end + state <= TRANSLATE2; + end + else if (state == TRANSLATE2) begin + // Actualiza las 8 semifilas del teclado con la segunda tecla + if (~released) begin + row[keyrow2] <= row[keyrow2] & ~keycol2; + end + else begin + row[keyrow2] <= row[keyrow2] | keycol2; + end + state <= TRANSLATE3; + end + else if (state == TRANSLATE3) begin + // Actualiza modificadores + if (~released) + modifiers <= modifiers | keymodifiers; + else + modifiers <= modifiers & ~keymodifiers; + + // Y de la misma forma tendria que actualizar el joystick, resets y los user_toogles + if (~released) + {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} <= {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} | joystate; + else + {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} <= {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} & ~joystate; + + if (~released) + {rmaster_reset,ruser_reset,ruser_nmi} <= {rmaster_reset,ruser_reset,ruser_nmi} | signalstate; + else + {rmaster_reset,ruser_reset,ruser_nmi} <= {rmaster_reset,ruser_reset,ruser_nmi} & ~signalstate; + + if (~released) + ruser_toggles <= ruser_toggles | togglestate; + else + ruser_toggles <= ruser_toggles & ~togglestate; + + //state <= UPDCOUNTERS1; + state <= IDLE; + end + else if (state == CPUTIME) begin + if (rewind == 1'b1) begin + cpuaddr = 14'h0000; + state <= IDLE; + end + else if (cpuread == 1'b1) begin + addr <= cpuaddr; + state <= CPUREAD; + end + else if (cpuwrite == 1'b1) begin + addr <= cpuaddr; + state <= CPUWRITE; + end + else + state <= IDLE; + end + else if (state == CPUREAD) begin // CPU wants to read from keymap + dout <= keymap[addr]; + state <= CPUINCADD; + end + else if (state == CPUWRITE) begin + keymap[addr] <= din; + state <= CPUINCADD; + end + else if (state == CPUINCADD) begin + if (cpuread == 1'b0 && cpuwrite == 1'b0) begin + cpuaddr <= cpuaddr + 1; + state <= IDLE; + end + end +// else if (state == UPDCOUNTERS1) begin +// if (~released) +// keycount <= keycount + 4'b0001; // suma 1 al contador de pulsaciones +// else if (released && keycount != 4'b0000) +// keycount <= keycount + 4'b1111; // o le resta 1 al contador de pulsaciones, pero sin bajar de 0 +// state <= UPDCOUNTERS2; +// end +// else if (state == UPDCOUNTERS2) begin +// if (keycount == 4'b0000) // si es la última tecla soltada, limpia la matriz de teclado del Spectrum +// state <= CLEANMATRIX; +// else +// state <= IDLE; +// end + else begin + state <= IDLE; + end + end +endmodule diff --git a/cores/Spectrum/scratch_register.v b/cores/Spectrum/scratch_register.v new file mode 100644 index 0000000..acdd67c --- /dev/null +++ b/cores/Spectrum/scratch_register.v @@ -0,0 +1,43 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 01:22:53 06/15/2015 +// Design Name: +// Module Name: scratch_register +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module scratch_register( + input wire clk, + input wire poweron_rst_n, + input wire [7:0] zxuno_addr, + input wire zxuno_regrd, + input wire zxuno_regwr, + input wire [7:0] din, + output reg [7:0] dout, + output wire oe_n + ); + + parameter SCRATCH = 8'hFE; + + assign oe_n = ~(zxuno_addr == SCRATCH && zxuno_regrd == 1'b1); + reg [7:0] scratch = 8'h00; // initial value + always @(posedge clk) begin + if (poweron_rst_n == 1'b0) + scratch <= 8'h00; // or after a hardware reset (not implemented yet) + else if (zxuno_addr == SCRATCH && zxuno_regwr == 1'b1) + scratch <= din; + dout <= scratch; + end +endmodule diff --git a/cores/Spectrum/tld_zxuno.bld b/cores/Spectrum/tld_zxuno.bld index 549f3e7..63d1c6c 100644 --- a/cores/Spectrum/tld_zxuno.bld +++ b/cores/Spectrum/tld_zxuno.bld @@ -5,7 +5,7 @@ Command Line: A:\ZZ\Xilinx\12.1\ISE_DS\ISE\bin\nt64\unwrapped\ngdbuild.exe -filter iseconfig/filter.filter -intstyle ise -dd _ngo -nt timestamp -uc pines_zxuno.ucf -p xc6slx9-tqg144-3 tld_zxuno.ngc tld_zxuno.ngd -Reading NGO file "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.ngc" ... +Reading NGO file "A:/zxuno/cores/spectrum_v2_spartan6/test16/tld_zxuno.ngc" ... Gathering constraint information from source properties... Done. @@ -27,10 +27,10 @@ NGDBUILD Design Results Summary: Number of errors: 0 Number of warnings: 0 -Total memory usage is 157796 kilobytes +Total memory usage is 155192 kilobytes Writing NGD file "tld_zxuno.ngd" ... -Total REAL time to NGDBUILD completion: 5 sec -Total CPU time to NGDBUILD completion: 5 sec +Total REAL time to NGDBUILD completion: 10 sec +Total CPU time to NGDBUILD completion: 10 sec Writing NGDBUILD log file "tld_zxuno.bld"... diff --git a/cores/Spectrum/tld_zxuno.cmd_log b/cores/Spectrum/tld_zxuno.cmd_log index 25b7cb3..d926d32 100644 --- a/cores/Spectrum/tld_zxuno.cmd_log +++ b/cores/Spectrum/tld_zxuno.cmd_log @@ -1,30 +1,6 @@ -xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.syr" +xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test16/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test16/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test16/tld_zxuno.syr" ngdbuild -filter "iseconfig/filter.filter" -intstyle ise -dd _ngo -nt timestamp -uc pines_zxuno.ucf -p xc6slx9-tqg144-3 tld_zxuno.ngc tld_zxuno.ngd map -filter "iseconfig/filter.filter" -intstyle ise -p xc6slx9-tqg144-3 -w -ol high -xe n -t 1 -xt 0 -register_duplication off -global_opt speed -equivalent_register_removal on -ir off -pr off -lc off -power off -o tld_zxuno_map.ncd tld_zxuno.ngd tld_zxuno.pcf -par -filter "iseconfig/filter.filter" -w -intstyle ise -ol high tld_zxuno_map.ncd tld_zxuno.ncd tld_zxuno.pcf -trce -filter A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter -intstyle ise -v 3 -s 3 -n 3 -fastpaths -xml tld_zxuno.twx tld_zxuno.ncd -o tld_zxuno.twr tld_zxuno.pcf -ucf pines_zxuno.ucf -bitgen -filter "iseconfig/filter.filter" -intstyle ise -f tld_zxuno.ut tld_zxuno.ncd -xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.syr" +xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test16/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test16/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test16/tld_zxuno.syr" ngdbuild -filter "iseconfig/filter.filter" -intstyle ise -dd _ngo -nt timestamp -uc pines_zxuno.ucf -p xc6slx9-tqg144-3 tld_zxuno.ngc tld_zxuno.ngd map -filter "iseconfig/filter.filter" -intstyle ise -p xc6slx9-tqg144-3 -w -ol high -xe n -t 1 -xt 0 -register_duplication off -global_opt speed -equivalent_register_removal on -ir off -pr off -lc off -power off -o tld_zxuno_map.ncd tld_zxuno.ngd tld_zxuno.pcf -par -filter "iseconfig/filter.filter" -w -intstyle ise -ol high tld_zxuno_map.ncd tld_zxuno.ncd tld_zxuno.pcf -trce -filter A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter -intstyle ise -v 3 -s 3 -n 3 -fastpaths -xml tld_zxuno.twx tld_zxuno.ncd -o tld_zxuno.twr tld_zxuno.pcf -ucf pines_zxuno.ucf -bitgen -filter "iseconfig/filter.filter" -intstyle ise -f tld_zxuno.ut tld_zxuno.ncd -xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.syr" -ngdbuild -filter "iseconfig/filter.filter" -intstyle ise -dd _ngo -nt timestamp -uc pines_zxuno.ucf -p xc6slx9-tqg144-3 tld_zxuno.ngc tld_zxuno.ngd -map -filter "iseconfig/filter.filter" -intstyle ise -p xc6slx9-tqg144-3 -w -ol high -xe n -t 1 -xt 0 -register_duplication off -global_opt speed -equivalent_register_removal on -ir off -pr off -lc off -power off -o tld_zxuno_map.ncd tld_zxuno.ngd tld_zxuno.pcf -par -filter "iseconfig/filter.filter" -w -intstyle ise -ol high tld_zxuno_map.ncd tld_zxuno.ncd tld_zxuno.pcf -trce -filter A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter -intstyle ise -v 3 -s 3 -n 3 -fastpaths -xml tld_zxuno.twx tld_zxuno.ncd -o tld_zxuno.twr tld_zxuno.pcf -ucf pines_zxuno.ucf -bitgen -filter "iseconfig/filter.filter" -intstyle ise -f tld_zxuno.ut tld_zxuno.ncd -xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.syr" -ngdbuild -filter "iseconfig/filter.filter" -intstyle ise -dd _ngo -nt timestamp -uc pines_zxuno.ucf -p xc6slx9-tqg144-3 tld_zxuno.ngc tld_zxuno.ngd -map -filter "iseconfig/filter.filter" -intstyle ise -p xc6slx9-tqg144-3 -w -ol high -xe n -t 1 -xt 0 -register_duplication off -global_opt speed -equivalent_register_removal on -ir off -pr off -lc off -power off -o tld_zxuno_map.ncd tld_zxuno.ngd tld_zxuno.pcf -par -filter "iseconfig/filter.filter" -w -intstyle ise -ol high tld_zxuno_map.ncd tld_zxuno.ncd tld_zxuno.pcf -trce -filter A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter -intstyle ise -v 3 -s 3 -n 3 -fastpaths -xml tld_zxuno.twx tld_zxuno.ncd -o tld_zxuno.twr tld_zxuno.pcf -ucf pines_zxuno.ucf -bitgen -filter "iseconfig/filter.filter" -intstyle ise -f tld_zxuno.ut tld_zxuno.ncd -xst -intstyle ise -filter "A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter" -ifn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.xst" -ofn "A:/zxuno/cores/spectrum_v2_spartan6/test14/tld_zxuno.syr" -ngdbuild -filter "iseconfig/filter.filter" -intstyle ise -dd _ngo -nt timestamp -uc pines_zxuno.ucf -p xc6slx9-tqg144-3 tld_zxuno.ngc tld_zxuno.ngd -map -filter "iseconfig/filter.filter" -intstyle ise -p xc6slx9-tqg144-3 -w -ol high -xe n -t 1 -xt 0 -register_duplication off -global_opt speed -equivalent_register_removal on -ir off -pr off -lc off -power off -o tld_zxuno_map.ncd tld_zxuno.ngd tld_zxuno.pcf -par -filter "iseconfig/filter.filter" -w -intstyle ise -ol high tld_zxuno_map.ncd tld_zxuno.ncd tld_zxuno.pcf -trce -filter A:/zxuno/cores/spectrum_v2_spartan6/test14/iseconfig/filter.filter -intstyle ise -v 3 -s 3 -n 3 -fastpaths -xml tld_zxuno.twx tld_zxuno.ncd -o tld_zxuno.twr tld_zxuno.pcf -ucf pines_zxuno.ucf -bitgen -filter "iseconfig/filter.filter" -intstyle ise -f tld_zxuno.ut tld_zxuno.ncd diff --git a/cores/Spectrum/tld_zxuno.prj b/cores/Spectrum/tld_zxuno.prj index ccf47f2..ad1fb09 100644 --- a/cores/Spectrum/tld_zxuno.prj +++ b/cores/Spectrum/tld_zxuno.prj @@ -1,5 +1,5 @@ -vhdl work "T80_Pack.vhd" vhdl work "T80_Reg.vhd" +vhdl work "T80_Pack.vhd" vhdl work "T80_MCode.vhd" vhdl work "T80_ALU.vhd" vhdl work "T80.vhd" @@ -7,7 +7,7 @@ vhdl work "YM2149_linmix.vhd" vhdl work "T80a.vhd" verilog work "spi.v" verilog work "rom.v" -verilog work "pal_sync_generator_progressive.v" +verilog work "pal_sync_generator_sinclair.v" vhdl work "mapa_teclado_es.vhd" verilog work "lut.v" verilog work "dp_memory.v" @@ -15,10 +15,12 @@ verilog work "zxunoregs.v" verilog work "ula_radas.v" verilog work "tv80_to_t80_wrapper.v" verilog work "turbosound.v" -vhdl work "ps2k.vhd" +vhdl work "ps2k_mcleod.vhd" verilog work "memory.v" +verilog work "joystick_protocols.v" verilog work "flash_spi.v" +verilog work "coreid.v" verilog work "audio_management.v" verilog work "zxuno.v" -verilog work "relojes.v" +verilog work "relojes_pll.v" verilog work "tld_zxuno.v" diff --git a/cores/Spectrum/tld_zxuno.v b/cores/Spectrum/tld_zxuno.v index 008226f..10970b0 100644 --- a/cores/Spectrum/tld_zxuno.v +++ b/cores/Spectrum/tld_zxuno.v @@ -29,8 +29,8 @@ module tld_zxuno ( output wire [2:0] b, output wire csync, input wire ear, - input wire clkps2, - input wire dataps2, + inout wire clkps2, + inout wire dataps2, output wire audio_out_left, output wire audio_out_right, output wire stdn, diff --git a/cores/Spectrum/tld_zxuno.xst b/cores/Spectrum/tld_zxuno.xst index bbcc34a..cabdc88 100644 --- a/cores/Spectrum/tld_zxuno.xst +++ b/cores/Spectrum/tld_zxuno.xst @@ -37,7 +37,7 @@ run -rom_style Auto -auto_bram_packing NO -resource_sharing NO --async_to_sync NO +-async_to_sync YES -shreg_min_size 2 -use_dsp48 auto -iobuf YES diff --git a/cores/Spectrum/ula_radas.v b/cores/Spectrum/ula_radas.v index e109ec7..84e54d5 100644 --- a/cores/Spectrum/ula_radas.v +++ b/cores/Spectrum/ula_radas.v @@ -85,7 +85,7 @@ module ula_radas ( assign clkdac = clk7; assign clkay = hc[0]; - assign clkkbd = hc[4]; + assign clkkbd = clk7; /* hc[4] */ pal_sync_generator_sinclair syncs ( .clk(clk7), diff --git a/cores/Spectrum/webtalk_pn.xml b/cores/Spectrum/webtalk_pn.xml index a64f981..81270ee 100644 --- a/cores/Spectrum/webtalk_pn.xml +++ b/cores/Spectrum/webtalk_pn.xml @@ -3,11 +3,11 @@ - +
- - + +
@@ -21,7 +21,7 @@ This means code written to parse this file will need to be revisited each subseq - + @@ -31,11 +31,13 @@ This means code written to parse this file will need to be revisited each subseq - - + + + + @@ -51,8 +53,8 @@ This means code written to parse this file will need to be revisited each subseq - - + +
diff --git a/cores/Spectrum/zxuno.gise b/cores/Spectrum/zxuno.gise index c781d58..8ca6142 100644 --- a/cores/Spectrum/zxuno.gise +++ b/cores/Spectrum/zxuno.gise @@ -22,9 +22,105 @@ - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cores/Spectrum/zxuno.v b/cores/Spectrum/zxuno.v index a57e471..6061627 100644 --- a/cores/Spectrum/zxuno.v +++ b/cores/Spectrum/zxuno.v @@ -31,8 +31,8 @@ module zxuno ( output wire [2:0] g, output wire [2:0] b, output wire csync, - input wire clkps2, - input wire dataps2, + inout wire clkps2, + inout wire dataps2, input wire ear, output wire audio_out, @@ -88,6 +88,7 @@ module zxuno ( // Señales de acceso a registro de direcciones ZX-Uno wire [7:0] zxuno_addr_to_cpu; // al bus de datos de entrada del Z80 wire [7:0] zxuno_addr; // direccion de registro actual + wire regaddr_changed; // indica que se ha escrito un nuevo valor en el registro de direcciones wire oe_n_zxunoaddr; // el dato en el bus de entrada del Z80 es válido wire zxuno_regrd; // Acceso de lectura en el puerto de datos de ZX-Uno wire zxuno_regwr; // Acceso de escritura en el puerto de datos del ZX-Uno @@ -108,19 +109,32 @@ module zxuno ( wire [4:0] kbdcol; wire [7:0] kbdrow; wire mrst_n,rst_n; // los dos resets suministrados por el teclado - wire [7:0] scancode; // scancode original desde el teclado PC - wire read_scancode = (zxuno_addr==8'h04 && zxuno_regrd); + wire [7:0] scancode_dout; // scancode original desde el teclado PC + wire oe_n_scancode; + wire [7:0] keymap_dout; + wire oe_n_keymap; + wire [7:0] kbstatus_dout; + wire oe_n_kbstatus; - // Interfaz kempston + // Interfaz joystick configurable + wire oe_n_joystick; wire [4:0] kbd_joy; - wire [4:0] db9_joy = {~joyfire, ~joyup, ~joydown, ~joyleft, ~joyright}; - wire oe_n_kempston = !(!iorq_n && !rd_n && cpuaddr[7:0]==8'd31); + wire [7:0] joystick_dout; + wire [4:0] kbdcol_to_ula; // Configuración ULA wire timming_ula; wire issue2_keyboard; wire disable_contention; wire access_to_screen; + + // CoreID + wire oe_n_coreid; + wire [7:0] coreid_dout; + + // Scratch register + wire oe_n_scratch; + wire [7:0] scratch_dout; assign kbdrow = cpuaddr[15:8]; // las filas del teclado son A8-A15 de la CPU @@ -128,10 +142,14 @@ module zxuno ( // conectados a ella. assign cpudin = (oe_n_romyram==1'b0)? memory_dout : (oe_n_ay==1'b0)? ay_dout : - (oe_n_kempston==1'b0)? {3'b000,(kbd_joy/* | db9_joy*/)} : + (oe_n_joystick==1'b0)? joystick_dout : (oe_n_zxunoaddr==1'b0)? zxuno_addr_to_cpu : (oe_n_spi==1'b0)? spi_dout : - (read_scancode==1'b1)? scancode : + (oe_n_scancode==1'b0)? scancode_dout : + (oe_n_kbstatus==1'b0)? kbstatus_dout : + (oe_n_coreid==1'b0)? coreid_dout : + (oe_n_keymap==1'b0)? keymap_dout : + (oe_n_scratch==1'b0)? scratch_dout : ula_dout; tv80n_wrapper el_z80 ( @@ -185,15 +203,15 @@ module zxuno ( // I/O ports .ear(ear), - .mic(mic), - .spk(spk), - .kbd(kbdcol), - .clkay(clkay), - .clkdac(clkdac), - .clkkbd(clkkbd), - .issue2_keyboard(issue2_keyboard), - .timming(timming_ula), - .disable_contention(disable_contention), + .mic(mic), + .spk(spk), + .kbd(kbdcol_to_ula), + .clkay(clkay), + .clkdac(clkdac), + .clkkbd(clkkbd), + .issue2_keyboard(issue2_keyboard), + .timming(timming_ula), + .disable_contention(disable_contention), // Video .r(r), @@ -204,8 +222,7 @@ module zxuno ( zxunoregs addr_reg_zxuno ( .clk(clk7), - .rst_n(rst_n), - .mrst_n(mrst_n & power_on_reset_n), + .rst_n(rst_n & mrst_n & power_on_reset_n), .a(cpuaddr), .iorq_n(iorq_n), .rd_n(rd_n), @@ -215,7 +232,8 @@ module zxuno ( .oe_n(oe_n_zxunoaddr), .addr(zxuno_addr), .read_from_reg(zxuno_regrd), - .write_to_reg(zxuno_regwr) + .write_to_reg(zxuno_regwr), + .regaddr_changed(regaddr_changed) ); flash_and_sd cacharros_con_spi ( @@ -283,19 +301,87 @@ module zxuno ( .sram_we_n(sram_we_n) ); - ps2k el_teclado ( - .clk(clkkbd), - .ps2clk(clkps2), - .ps2data(dataps2), +// ps2k el_teclado ( +// .clk(clkkbd), +// .ps2clk(clkps2), +// .ps2data(dataps2), +// .rows(kbdrow), +// .cols(kbdcol), +// .joy(kbd_joy), // Implementación joystick kempston en teclado numerico +// .scancode(scancode), // El scancode original desde el teclado +// .rst(rst_n), // esto son salidas, no entradas +// .nmi(nmi_n), // Señales de reset y NMI +// .mrst(mrst_n) // generadas por pulsaciones especiales del teclado +// ); + + ps2_keyb el_teclado ( + .clk(clk), + .clkps2(clkps2), + .dataps2(dataps2), .rows(kbdrow), .cols(kbdcol), .joy(kbd_joy), // Implementación joystick kempston en teclado numerico - .scancode(scancode), // El scancode original desde el teclado - .rst(rst_n), // esto son salidas, no entradas - .nmi(nmi_n), // Señales de reset y NMI - .mrst(mrst_n) // generadas por pulsaciones especiales del teclado + .rst_out_n(rst_n), // esto son salidas, no entradas + .nmi_out_n(nmi_n), // Señales de reset y NMI + .mrst_out_n(mrst_n), // generadas por pulsaciones especiales del teclado + //---------------------------- + .zxuno_addr(zxuno_addr), + .zxuno_regrd(zxuno_regrd), + .zxuno_regwr(zxuno_regwr), + .regaddr_changed(regaddr_changed), + .din(cpudout), + .keymap_dout(keymap_dout), + .oe_n_keymap(oe_n_keymap), + .scancode_dout(scancode_dout), + .oe_n_scancode(oe_n_scancode), + .kbstatus_dout(kbstatus_dout), + .oe_n_kbstatus(oe_n_kbstatus) ); + + joystick_protocols los_joysticks ( + .clk(clk), + //-- cpu interface + .a(cpuaddr), + .iorq_n(iorq_n), + .rd_n(rd_n), + .din(cpudout), + .dout(joystick_dout), + .oe_n(oe_n_joystick), + //-- interface with ZXUNO reg bank + .zxuno_addr(zxuno_addr), + .zxuno_regrd(zxuno_regrd), + .zxuno_regwr(zxuno_regwr), + //-- actual joystick and keyboard signals + .kbdjoy_in(kbd_joy), + .db9joy_in({joyfire, joyup, joydown, joyleft, joyright}), + .kbdcol_in(kbdcol), + .kbdcol_out(kbdcol_to_ula), + .vertical_retrace_int_n(int_n) // this is used as base clock for autofire + ); + + coreid identificacion_del_core ( + .clk(clk), + .rst_n(rst_n & mrst_n & power_on_reset_n), + .zxuno_addr(zxuno_addr), + .zxuno_regrd(zxuno_regrd), + .regaddr_changed(regaddr_changed), + .dout(coreid_dout), + .oe_n(oe_n_coreid) + ); + + scratch_register scratch ( + .clk(clk), + .poweron_rst_n(power_on_reset_n), + .zxuno_addr(zxuno_addr), + .zxuno_regrd(zxuno_regrd), + .zxuno_regwr(zxuno_regwr), + .din(cpudout), + .dout(scratch_dout), + .oe_n(oe_n_scratch) + ); + + /////////////////////////////////// // AY-3-8912 SOUND /////////////////////////////////// diff --git a/cores/Spectrum/zxuno.xise b/cores/Spectrum/zxuno.xise index 2c017ad..4877c05 100644 --- a/cores/Spectrum/zxuno.xise +++ b/cores/Spectrum/zxuno.xise @@ -29,7 +29,10 @@ - + + + + @@ -125,12 +128,33 @@ - + - - + + + + + + + + + + + + + + + + + + + + + + + @@ -160,7 +184,7 @@ - + @@ -240,7 +264,7 @@ - + @@ -262,7 +286,7 @@ - + @@ -328,7 +352,7 @@ - + diff --git a/cores/Spectrum/zxunoregs.v b/cores/Spectrum/zxunoregs.v index 86e2694..1c5e021 100644 --- a/cores/Spectrum/zxunoregs.v +++ b/cores/Spectrum/zxunoregs.v @@ -23,7 +23,6 @@ module zxunoregs ( input wire clk, input wire rst_n, - input wire mrst_n, input wire [15:0] a, input wire iorq_n, input wire rd_n, @@ -33,7 +32,8 @@ module zxunoregs ( output reg oe_n, output wire [7:0] addr, output wire read_from_reg, - output wire write_to_reg + output wire write_to_reg, + output wire regaddr_changed ); parameter @@ -43,12 +43,20 @@ module zxunoregs ( // Manages register addr ($00 - $FF) reg [7:0] raddr = 8'h00; assign addr = raddr; + reg rregaddr_changed = 1'b0; + assign regaddr_changed = rregaddr_changed; always @(posedge clk) begin - if (!rst_n) + if (!rst_n) begin raddr <= 8'h00; - else if (!iorq_n && a==IOADDR && !wr_n) + rregaddr_changed <= 1'b1; + end + else if (!iorq_n && a==IOADDR && !wr_n) begin raddr <= din; + rregaddr_changed <= 1'b1; + end + else + rregaddr_changed <= 1'b0; end always @* begin