#include "exec/types.h" #include "hp11/hp11.h" #include "hp11/kbd.h" #include "hp11/codes.h" #include "hp11/io.h" /* Macros to initialise one field of the keyboard structure to a particular type. This simpilfies (& clarifies) this initialisation. */ #define CODE(code) {Instruction, (Decoder)(code) } #define ACT(act) {Action, (Decoder)(act) } #define PREFIX(adr) {Prefix, (adr) } #define INVALID() {Invalid, NULL } /* Often used macros which return their agument signaling that it is an instruction, action or error */ #define RETINS(val) { *code = (val); return(Instruction); } #define RETACT(val) { *code = (val); return(Action); } #define RETERR(key) { *code = (key); return(Invalid); } /* Keys which can follow GTO (or GSB). A -1 indicates am invalid sequence, otherwise the value is the offset to add to KGTO to obtain the corresponding instruction. IGTO_LINE is different and valid only for GTO, it indicates a GTO .nnn action */ static BYTE gto_decode[NUMKEYS] = { 10, 11, 12, 13, 14, -1, 7, 8, 9, -1, -1, -1, -1, -1, OIND_G, -1, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1, 0, IGTO_LINE, -1, -1, -1, -1 }; /* For STO & RCL, cf above */ static BYTE sto_decode[NUMKEYS] = { -1, -1, -1, -1, -1, -1, 7, 8, 9, ODIV, -1, -1, -1, OIND_R, OI, -1, 4, 5, 6, OMUL, -1, -1, -1, -1, -1, KRANDOM, 1, 2, 3, OSUB, -1, -1, -1, -1, -1, -1, 0, KPOINT, KSIGMA_PLUS, OPLUS, -1, -1 }; /* Functions which take a numeric argument only (eg eng) can use the numbers from gto_decode, considering as invalid what isn't a number between 1 & 10 */ #define nb_decode gto_decode /* Read 3 digits for GTO .nnn & return the value in line. If something other than a number is entered, return the keycode of the first incorrect code & FALSE */ static BOOL GetLine(short *line) { register int cnt = 0, key; register int dec; *line = 0; do { key = GetKey(); dec = nb_decode[key]; /* Get numeric value */ if (dec >= 0 && dec <= 9) { /* It is a digit */ cnt++; *line = *line * 10 + dec; } else { /* error */ *line = key; return(FALSE); } } while (cnt < 3); /* 3 digits reads */ return(TRUE); } /* Decoder routine for FIX, SCI, ENG, SF, CF, Set. code returns the instruction/action/keycode, start is the offset for the instruction being decoded (eg KFIX), max is the maximum value which can be accepted (eg 1 for SF). For SCI & ENG, a number beyond their max (7) is treated as if it was the max value (So if you type 'f SCI 8' you will get 'f SCI 7' */ static enum KeyTypes NBDec(short *code, int start, int max) { register int key, dec; key = GetKey(); dec = nb_decode[key]; if (dec >= 0 && dec <= 9) { /* Is a digit */ if (dec <= max) RETINS(start + dec) /* valid ins */ else if (start == KSCI || start == KENG) RETINS(start + max) /* Special treatment for SCI & ENG */ } RETERR(key); } /* Decoding for HYP & ArcHYP */ static enum KeyTypes HypDec(short *code, int start) { int key; key = GetKey(); if (key >= 12 /* SIN */ && key <= 14 /* TAN */) RETINS(start + key - 12) else RETERR(key); } /* Decoding for GTO, GSB & LBL */ static enum KeyTypes JMPDec(short *code, int start) { register int key, dec; short val; key = GetKey(); dec = gto_decode[key]; if (dec >= 0 && dec <= 15) RETINS(start + dec); /* 0 to 9, A to E */ switch (dec) { case IGTO_LINE: if (start == KGTO) /* GTO .nnn */ if (GetLine(&val)) RETACT(IGTO_LINE + val) else RETERR(val); case OIND_G: if (start != KLBL) RETINS(start + OIND_G); /* GTO/GSB I */ } RETERR(key); } /* Decoding for STO & RCL, deals with all possible STO's */ static enum KeyTypes REGDec(short *code, int start) { register int dec, key, oldoff, offset = 0; do { key = GetKey(); dec = sto_decode[key]; oldoff = offset; if ((dec >= 0 && dec <= 9) /* 0 to 9 end an instruction */ || /* I & (i) end an instruction if no . was typed before. This is visible if the offset (ignoring + - * /) is 10 */ ((offset % OPLUS) != 10 && (dec == OI || dec == OIND_R))) RETINS(start + offset + dec); switch (dec) { /* Special cases & offsets */ case KRANDOM: if (offset == 0 && start == KSTO) RETINS(KSTO_RANDOM); /* STO Random */ case KSIGMA_PLUS: if (offset == 0 && start == KRCL) RETINS(KRCL_SIGMA); /* Recall stats */ case KPOINT: if ((offset % OPLUS) == 0) offset += 10; /* Only one . allowed */ case OPLUS: case ODIV: case OMUL: case OSUB: /* + - * / only if none yet */ if (offset == 0 && start == KSTO) offset = dec; } } while (offset != oldoff); /* if offset not changed then there was an error (the loop is repeated when the offset changes) */ RETERR(key); } /* Decoding for prefixes */ /* --------------------- */ static enum KeyTypes FIXDec(short *code) { return(NBDec(code, KFIX, 9)); } static enum KeyTypes SCIDec(short *code) { return(NBDec(code, KSCI, 7)); } static enum KeyTypes ENGDec(short *code) { return(NBDec(code, KENG, 7)); } static enum KeyTypes SFDec(short *code) { return(NBDec(code, KFLAGS + OSF, 1)); } static enum KeyTypes SETDec(short *code) { return(NBDec(code, KFLAGS + OSET, 1)); } static enum KeyTypes CFDec(short *code) { return(NBDec(code, KFLAGS + OCF, 1)); } static enum KeyTypes HYPDec(short *code) { return(HypDec(code, KHYP)); } static enum KeyTypes ARCHYPDec(short *code) { return(HypDec(code, KARCHYP)); } static enum KeyTypes LBLDec(short *code) { return(JMPDec(code, KLBL)); } static enum KeyTypes GTODec(short *code) { return(JMPDec(code, KGTO)); } static enum KeyTypes GSBDec(short *code) { return(JMPDec(code, KGSB)); } static enum KeyTypes STODec(short *code) { return(REGDec(code, KSTO)); } static enum KeyTypes RCLDec(short *code) { return(REGDec(code, KRCL)); } /* The main kbd, f & g */ /* ------------------- */ struct Key mainKbd[3 * NUMKEYS] = { /* First the main keyboard (unshifted). All the keys which can be entered MUST not be INVALID(), otherwise the program enters an infinite loop */ CODE(KSQRT), CODE(KEXP), CODE(KEXP10), CODE(KEXP_YX), CODE(KINV), CODE(KCHS), CODE(KFIG + 7), CODE(KFIG + 8), CODE(KFIG + 9), CODE(KDIV), ACT(ISST), PREFIX(GTODec), CODE(KTRIG + OSIN), CODE(KTRIG + OCOS), CODE(KTRIG + OTAN), CODE(KEEX), CODE(KFIG + 4), CODE(KFIG + 5), CODE(KFIG + 6), CODE(KMUL), CODE(KR_S), PREFIX(GSBDec), CODE(KRDN), CODE(KEXG_XY), ACT(IBACK), CODE(KENTER), CODE(KFIG + 1), CODE(KFIG + 2), CODE(KFIG + 3), CODE(KSUB), ACT(ION), INVALID(), /* Never tested : f */ INVALID(), /* Never tested : g */ PREFIX(STODec), PREFIX(RCLDec), INVALID(), /* This key does not exist : it is hidden by ENTER */ CODE(KFIG + 0), CODE(KPOINT), CODE(KSIGMA_PLUS), CODE(KPLUS), ACT(IRESET), /* These 2 are pseudo-keys */ ACT(IDISPLAY), /* now f codes, which can be INVALID() */ CODE(KGSB + OA), CODE(KGSB + OB), CODE(KGSB + OC), CODE(KGSB + OD), CODE(KGSB + OE), CODE(KPI), PREFIX(FIXDec), PREFIX(SCIDec), PREFIX(ENGDec), CODE(KX_LE_Y), PREFIX(LBLDec), PREFIX(HYPDec), CODE(KEXG_X_IND), CODE(KRCL + OIND_R), CODE(KRCL + OI), CODE(KRECT), CODE(KEXG_XI), CODE(KDSE), CODE(KISG), CODE(KX_GT_Y), CODE(KPSE), CODE(KCLR_SIGMA), ACT(ICLR_PRGM), CODE(KCLR_REG), ACT(ICLR_PREFIX), CODE(KRANDOM), CODE(KPERM), CODE(KHMS), CODE(KTO_RAD), CODE(KX_NE_Y), INVALID(), INVALID(), INVALID(), /* ON, f & g */ CODE(KFRAC), ACT(IUSER), INVALID(), /* dosen't exist */ CODE(KFACT), CODE(KESTIMATE), CODE(KLR), CODE(KX_EQ_Y), INVALID(), INVALID(), /* finally, g codes */ CODE(KSQR), CODE(KLN), CODE(KLOG), CODE(KPERC), CODE(KDELTA_PERC), CODE(KABS), CODE(KDEG), CODE(KRAD), CODE(KGRD), CODE(KX_LT_0), ACT(IBST), PREFIX(ARCHYPDec), CODE(KARC + OSIN), CODE(KARC + OCOS), CODE(KARC + OTAN), CODE(KPOLAR), PREFIX(SFDec), PREFIX(CFDec), PREFIX(SETDec), CODE(KX_GT_0), ACT(IP_R), CODE(KRTN), CODE(KRUP), CODE(KRND), CODE(KCLX), CODE(KLSTX), CODE(KCOMB), CODE(KHR), CODE(KTO_DEG), CODE(KX_NE_0), INVALID(), INVALID(), INVALID(), CODE(KINT), ACT(IMEM), INVALID(), CODE(KMEAN), CODE(KSDEV), CODE(KSIGMA_SUB), CODE(KX_EQ_0), INVALID(), INVALID() };