D8085AC ROM and 8279 finding keycodes - Page 1
Forum section: electronics / projects

author: Dom87
author_rank: Contributor
timestamp: May 24, 2020, 12:53:12 pm
content: From my last posthttps://www.eevblog.com/forum/projects/d8085ac-and-d27128d-extracting-program-from-eprom/, I have managed to extract the ROM from the 27128D.What I'm trying to do now is work out where the lookup table is for the 8279 Keyboard/Display interface that is used.I know what all the keycodes are in binary/hex, I just don't really know what I'm looking for in the disassembled ROM (using Dasmx140).The keyboard is in 2-key lockout encoded scan. CTRL + SHFT are not used, therefore always high.Any tips would be greatly appreciated.Thanks!An example list of the button codes:ButtonBinaryHex4811000011C34711000100C44911000101C54411001001C94311001010CA4111001100CC4211001101CD4511001110CE4611001111CF4011010000D03611010001D13511010010D23911010011D3

author: greenpossum
author_rank: Frequent Contributor
timestamp: May 24, 2020, 01:05:09 pm
content: If you can work out from the circuit where in the 8085 I/O space the 8279 is located you might be able to find the IN and OUT instructions that talk to it and go from there.

author: duak
author_rank: Super Contributor
timestamp: May 24, 2020, 05:40:44 pm
content: As greenpossum says, look for the in and out instructions to the 8279. With any luck, they will be localized to a few routines; initialization, check_for_keypressed, and get_key. The 8279 may also be connected to generate an interrupt request to the 8085. If so, the last two routines above may not read directly from the 8279 but from flag variables and buffers. The actual in and out instructions will be in Interrupt Service Routines that will set and reset the flag variables and place keypress codes in the buffers. The look-up table might be referenced at this level.if the above functions are localized to a few routines, then look for where those routines are called from. Hopefully, your disassembler can generate a symbol table, maybe with your help.

author: Dom87
author_rank: Contributor
timestamp: May 24, 2020, 06:53:06 pm
content: Thanks the replies.I believe it is using an interrupt (IRQ), so your response on the flag variables and buffers helps. As one thing I noticed is that my ROM doesn't have any IN/OUT commands.The IRQ (pin 4) of the 8279 goes to RST 5.5 of the 8085 (pin 9).I did think finding the prescaler might help as well, since I know this is set to 15 to achieve the 100KHz clock frequency.

author: duak
author_rank: Super Contributor
timestamp: May 24, 2020, 08:47:23 pm
content: Dom87, it's interesting that there are no in/out opcodes. Perhaps the 8279 is memory mapped and is accessed by memory reference instructions? Are you able to figure out where the 8279 CS (Chip Select) line comes from? Is the 8279 on the same board as the 8085 and are the data busses common?In the software listing, have you looked at the ISR that RST5.5 jumps to? If memory serves, the processor pushes the Program Counter contents on the stack then executes the code starting from 002CH.Are there any text strings in the ROM? eg., "Firmware V2.0" or "Compiled by x.y.z" It might give a hint on how to decipher the ROM contents. If the source code was written in a high level language and then compiled to give the machine code it might have been more convenient to memory map the peripheral device registers. This is because the 8085 does not have indirect input/ouput instructions where the port address is variable.

author: Dom87
author_rank: Contributor
timestamp: May 25, 2020, 09:20:24 pm
content: Thanks Duak.There isn't any text strings that have anything like that in it.They are both on the same board.From what I've found the data bus lines are shared with a number of other components, but it appears they are common with one another.8279-22 (CS) goes to a 74HCT138 (3-to-8 line decoder/multiplexer).There is a 74HCT138 that is used to select the different devices on the board.(8279 Keyboard & Display / 6264 Static RAM / 8253, etc).The 8279 pin 22 (CS) goes to pin 11 of the 74HCT138, which is Y4.74HCT138 Pins1 A08085-25 (A12)2 A18085-26 (A13)3 A28085-27 (A14)4 E18085-6 (TRAP) / Ground5 E28085-34 (IO-M)6 E38085-28 (A15)Based on the datasheet and the truth table, I would expect the 8279 CS line to be low (active) when...E1 = 0, E2 = 0, E3 = 1, EA2 = 1, A1 = 0, A0 = 0.HM6264 = Static RAM27128 = EPROM80858085 PinComponent & Pin8085 PinComponent & Pin1 (X1)21 (A8)27128-252 (X2)22 (A9)27128-243 (RST)8279-9 (RST)23 (A10)27128-214 (SOD)24 (A11)27128-235 (SID)25 (A12)27128-2 / 74HCT138-1 (A0)6 (TRAP)74HCT138-4 (E1) / Ground26 (A13)27128-26 / 74HCT138-2 (A1)7 (RST7.5)27 (A14)74HCT138-27 (A2)8 (RST6.5)28 (A15)27128-20 (CE) / 74HCT138-6 (E3)9 (RST5.5)8279-4 (IRQ)29 (S0)10 (INTR)30 (ALE)11 (INTA)31 (WR)8279-11 (WR)12 (AD0)8279-12 (DB0) / 27128-11 / 6264-1132 (RD)8279-10 (RD) / 27128-22 / 6264-2213 (AD1)8279-13 (DB1) / 27128-12 / 6264-1233 (S1)14 (AD2)8279-14 (DB2) / 27128-13 / 6264-1334 (IO-M)74HCT138-5 (E2)15 (AD3)8279-15 (DB3) / 27128-15 / 6264-1535 (RDY)16 (AD4)8279-16 (DB4) / 27128-16 / 6264-1636 (RST-IN)17 (AD5)8279-17 (DB5) / 27128-17 / 6264-1737 (CLK-OUT)18 (AD6)8279-18 (DB6) / 27128-18 / 6264-1838 (HLDA)19 (AD7)8279-19 (DB7) / 27128-19 / 6264-1939 (HOLD)20 (VSS)Ground/8279-2040 (VCC)+5V / 8279-40I've run out of time this evening to run through the code. But I shall have a look tomorrow.I have included it if anyone wanted to have a look and see if they could spot something.Dasmx140__reading_20200507_1926.txt(338.17 kB - downloaded 71 times.)Thanks again!

author: greenpossum
author_rank: Frequent Contributor
timestamp: May 25, 2020, 11:05:02 pm
content: Just one thing. I suspect that E1 pin 4 of the 138 and the TRAP pin 6 of the 8085 are both tied to ground.

author: Dom87
author_rank: Contributor
timestamp: May 26, 2020, 08:17:21 am
content: Quote from: greenpossum on May 25, 2020, 11:05:02 pmSpot on! Both E1 (4) and TRAP (6) are tied to ground. I've updated my previous post to keep things together.Thanks

author: greenpossum
author_rank: Frequent Contributor
timestamp: May 26, 2020, 02:05:50 pm
content: Looks like the 8279 is addressed at 0xCXXX addresses.Also you should trace where the interrupt vector RST5.5 jumps to.

author: Dom87
author_rank: Contributor
timestamp: May 27, 2020, 11:14:05 pm
content: Thanks Greenpossum.I am slowly but surely working out bits. Albeit a steep learning curve.I've at least identified the 8279 initialisation sequence when it is turned on.Code:04D1 : 21 01 C0"! "lxih,XC00104D4 : 36 08"6 "mvim,008H; 8279: Keyboard/Display = 16 8-Bit / Encoded 2-key Lockout (00001000)04D6 : 36 2F"6/"mvim,02FH; 8279: Prescaler for program clock (2F/47/00101111) 1.5MHz / 1504D8 : 36 A0"6 "mvim,0A0H; 8279: Display Write Inhibit Blanking (A0/160/10100000)04DA : 36 DF"6 "mvim,0DFH; 8279: Clear All (11011111)From what I think I understand now about the interrupts, they trigger the 8085 to run from fixed locations within the program.Address = 8 * RST No.So I would expect them to be here....Code:002A : 00" "nop002B : 00" "nop002C : C9" "ret; RST 5.5 Interrupt Vector Address? 8279: Keyboard/Display?;002D : 00" "nop002E : 00" "nop002F : 00" "nop0030 : 00" "nop0031 : 00" "nop0032 : 00" "nop0033 : 00" "nop0034 : C3 58 01" X "jmpL0158; RST 6.5 Interrupt Vector Address?;0037 : 00" "nop0038L0038:0038 : 00" "nop0039 : 00" "nop003A : 00" "nop003B : 00" "nop003C : C3 E4 03" "jmpL03E4; RST 7.5 Interrupt Vector Address? U22-5?What I don't quite understand is where 5.5 is supposed to go or do with a return command.

author: greenpossum
author_rank: Frequent Contributor
timestamp: May 27, 2020, 11:24:50 pm
content: It looks like the 8279 isn't set up to generate interrupts. The ret is just in case somehow the "impossible" happens, the 8085 will just resume what it was doing.Also the RST line is just a common reset, both are input pins.

author: Dom87
author_rank: Contributor
timestamp: June 12, 2020, 07:09:22 pm
content: Doh! Thanks GreenPossum. That should have been obvious really.To make more sense of what is going on in the program, I decided to have a look at how the databus and address lines are wired up to control each of the components on the main board.Its by no means perfect, but I have created a flow diagram which I think illustrates what is going on.and I think these are the address lines for each of the components.I believe the program loops round and round in this section here, until either an IRQ is triggered or a key-press is loaded into the keyboard RAM, which is checked periodically.Code:00AFL00AF:; ###################### Main Program??? ####################00AF : FB" "ei; Enable Interrupt00B0 : 3A 00 F9": "ldaXF90000B3 : E6 02" "ani002H00B5 : CC C5 02" "czL02C500B8 : 3A 60 B6":` "ldaXB66000BB : E6 10" "ani010H00BD : CA C9 00" "jzL00C9; Jump if no key command in RAM?00C0 : CD D2 00" "callL00D200C3 : CD 10 01" "callL011000C6 : C3 AF 00" "jmpL00AF; Repeat sub-routineWould I be right in believing that the E register is used for selecting the component address?e.g.mvi e,086Hmvi e,006Hmvi e,013HThanks!

author: duak
author_rank: Super Contributor
timestamp: June 12, 2020, 09:54:47 pm
content: It's been years, but I don't think so.opcode 3A, LDA <address> reads the byte at memory location <address> into AI think you would need:opcode 1A, LDAX D reads the byte at the memory location pointed to by DE into ACheers,

author: greenpossum
author_rank: Frequent Contributor
timestamp: June 13, 2020, 08:17:04 am
content: I assume you mean that the D register has been previously loaded with F8 and the E register is used to address the subunits enabled by U14. In that case you would be looking for 1A = ldax d like duak says, and its counterpart 12, stax d instructions.

author: westfw
author_rank: Super Contributor
timestamp: June 15, 2020, 06:31:53 am
content: Does it look like the SDK-85 source code that you can still find commented listings for?http://bitsavers.trailing-edge.com/components/intel/8085/9800451A_SDK-85_Users_Manual_Jul77.pdf

author: Dom87
author_rank: Contributor
timestamp: June 15, 2020, 12:08:11 pm
content: Thanks All.I shall take a look and see.

author: Dom87
author_rank: Contributor
timestamp: July 08, 2020, 11:43:43 pm
content: Thanks for the tips so far everyone.I think I've made some significant process, but I'm still not quite there yet, and I refuse to be beaten!It has been quite an enjoyable project learning how the older processors used to work.I was wondering if I could ask for some further advice on a particular section of code please? I'm not entirely sure what it is doing.Any help or guidance would be great.I found a particular sub-routine (L0DA5) that seems to validate/lookup the first character of a command string. For example; a command string might be "F12.4HZ". It seems to take the first character, e.g. 'F' and then checks a look-up table to ensure that it exists.It is clearly a loop routine, counting down from 10 in decimal (A in hex). I believe it adds 3 to the D register on every loop to increase the HL pair.I believe the HL pair refers to a particular address within the program, starting from 0DFE. Looking at this particular section of code, this seems to back up my understanding of what is going on.My question is this: If/When it does the look-up, does it take any notice of the op-codes, such as "Fmov b,m" or is it simply ignored?I'm trying to work out what value is used later on in the program.L0DA5Code:0DA5L0DA5:; ##### Validation/Lookup(?) Routine: This is only called from L0C59 when a command is in memory. ####0DA5 : 0E 0A" "mvic,00AH; L0DAD is loop and this initialises it as a countdown from 10.0DA7L0DA7:0DA7 : 21 FE 0D"! "lxih,00DFEH; Start of look-up table address?0DAA : 11 03 00" "lxid,00003H0DADL0DAD:; ### Loop - This seems to be validating the first command character. ###0DAD : BE" "cmpm; 'F'/46, 'A'/41, 'O'/4F, 'W'/57, 'M'/4D, 'N'/4E, 'Y'/59, 'S'/52, etc.0DAE : C8" "rz; Returns if zero. i.e. the character is a match.0DAF : 19" "dadd0DB0 : 0D" "dcrc; Decrements the countdown loop from 10 dec / A Hex.0DB1 : C2 AD 0D" "jnzL0DAD; If it reaches zero, then we know we have an error. I think.0DB4 : F6 80" "ori080H; Only reaches here if invalid command.0DB6 : C9" "ret0DFECode:0DFE : 46"F"movb,m0DFF : 20" "rim0E00 : 01 41 21" A!"lxib,02141H0E03 : 01 4F 22" O""lxib,0224FH0E06 : 01 57 23" W#"lxib,02357H0E09 : 04" "inrb0E0A : 4D"M"movc,l0E0B : 27"'"daa0E0C : 03" "inxb0E0D : 4E"N"movc,m0E0E : 2C","inrl0E0F : 02" "staxb0E10 : 59"Y"move,c0E11 : 30"0"sim0E12 : 02" "staxb0E13 : 52"R"movd,d0E14 : 2E 00". "mvil,000H0E16 : 53"S"movd,e0E17 : 2D"-"dcrl0E18 : 00" "nop0E19 : 5A"Z"move,dThanks for your help.

author: duak
author_rank: Super Contributor
timestamp: July 09, 2020, 02:52:32 am
content: It's been a long time since I worked with 8085 so I may have made a misteak or too.Your analysis of the code makes sense. Subroutine L0DA5 successfully exits with HL pointing to the command letter it matched.I edited the table at 0DFE to see if there was a pattern between the command letters. Since there are two bytes, I thought they might be the addresses of subroutines somewhere to do some particular task. That is, the code calling L0DA5 will increment HL by 1 and jump to or call the subroutine referenced by the two following bytes. I don't think so here because the first characters of the pair are too close together to identify subroutine entry points. And to answer your question, I don't think these bytes are opcodes.0DFE : 46 "F"20 010E01: 41 'A'21 010E04 : 4F 'O'22 010E09 : 57 'W'23 040E0A : 4D "M"27 030E0D : 4E "N"2C 020E10 : 59 "Y"30 020E13 : 52 "R"2E 000E16 : 53 "S"2D 000E19 : 5A "Z"The second byte of the pair could be the number, size or type of parameters that could be expected following the command letter. If so, the first byte of the pair could specify the variable that would receive the numbers following the command letter. It may be coincidence, but for the first few entries the sum of the two bytes is the first byte of the next pair. eg 20 + 01 = 21, 21 + 01 = 22, 22 + 01 = 23, 23 + 04 = 27 It breaks down after that but there might be some underlying relationship between the two bytes.We'd need more code to decipher what it's doing.

author: Dom87
author_rank: Contributor
timestamp: July 09, 2020, 03:27:37 pm
content: Thanks Duak. That makes complete sense and now looking at it from a slightly different perspective I can see that it is using the next value in the address.I've taken your idea of the table and restructured as to how I think it is looking up data.As you suggest, I think it is using the two values that follow the matched character. In the table below, these are columns '1st Val' and '2nd Val'.I think it loads the 1st value from the lookup table at 0C74 in L0C59, after it has performed the lookup for the first character by calling L0DA5 at 0C69.Any ideas what it might be doing between 0C74 and 0C77?I'm not sure I fully understand what the commands "xchg" and "db" are trying to do.L0DA5 (Shown in my previous post) is called from L0C59, which seems to be the main branch that loads a character in sequence and then validates/manipulates it.L0C59Main command routine. I believe this loads each character in the command string in sequence and performs checks.It appears to start with loading the first character. e.g. 'F' by calling L0DF4 and then validating it using the lookup table as described in the earlier post (same sub-routine).Code:0C59L0C59:; ########## Main command routine ##########0C59 : CD F4 0D" "callL0DF4; Retrieves the next character in the command string. I believe this is the first character.0C5C : 3A 26 B7":& "ldaXB7260C5F : B7" "oraa0C60 : C2 DA 0C" "jnzL0CDA0C63 : 7E"~"mova,m; I think a single character is moved into the A register.0C64 : FE 3F" ?"cpi03FH; Checks against 63 decimal. ASCII this is a question mark. Is that what it is checking for?0C66 : CA 36 0D" 6 "jzL0D36; Jump if character is 63 / Question mark. This will load the next character and try to validate it.0C69 : CD A5 0D" "callL0DA5; This seems to validate the first character command.0C6C : C2 83 0D" "jnzL0D83; Err Msg. Jump if first character not recognised? L0D83 places 91H into L register and 001 into the A register.0C6F : 3E 01"> "mvia,001H0C71 : 32 26 B7"2& "staXB7260C74 : 23"#"inxh; INcrementeXtended register. This looks at the 1st value in the lookup table after match (0DFE)0C75 : EB" "xchg; Exchange contents of HL register pair with DE register pair. Is the lookup table value? e.g. W = 23?;0C76 : ED" "db0EDH; directs the assembler to reserve one byte of memory and initialize the byte with the specified value;0C77 : 7C"|"mova,h0C78 : B7" "oraa0C79 : FA C5 0C" "jmL0CC5; Jump if minus0C7C : CA C5 0C" "jzL0CC5; Jump if zero. Basically this is jump if zero or less than.0C7F : 3D"="dcra0C80 : C2 8E 0C" "jnzL0C8E; Jumps if there is a command.0C83 : E5" "pushh0C84 : CD C6 0D" "callL0DC6; This seems to be finding the end of the command string. I think. Needs double-checking.0C87 : E1" "poph0C88 : DA 83 0D" "jcL0D83; Jump if carry. Error Msg. 9-10C8B : C3 7B 0D" { "jmpL0D7B;0C8EL0C8E:0C8E : E5" "pushh0C8F : CD F4 0D" "callL0DF4; Retrieves the next character in the command string.0C92 : CD B7 0D" "callL0DB7; This subtracts from the accumulator 30H. I believe this converts a hexadecimal number to a number.0C95 : E1" "poph0C96 : DA 83 0D" "jcL0D83; Error Msg. 9-10C99 : BC" "cmph0C9A : D2 83 0D" "jncL0D83; Jumps here if invalid command. It is known at at this point if it is an invalid command. Such as "N2"0C9D : 25"%"dcrh0C9E : 25"%"dcrh0C9F : 67"g"movh,a0CA0 : CA B5 0C" "jzL0CB5; Jump if zero. It jumps with command in memory. "N0"0CA3 : 7D"}"mova,l0CA4 : FE 23" #"cpi023H0CA6 : 7C"|"mova,h0CA7 : C2 B1 0C" "jnzL0CB1; Jump not zero.0CAA : D6 01" "sui001H; SUbtract Immediate from Accumulator0CAC : D2 B1 0C" "jncL0CB1; Jump no carry. It jumps here with "W2," in memory.0CAF : 3E 03"> "mvia,003HL0DF4I think this simply loads the next character in the string from memory.Code:0DF4L0DF4:; ##### This seems to retrieve the next character in the command #####0DF4 : 2A 28 B7"*( "lhldXB728; Load HL pair using Direct addressing from memory location0DF7 : 23"#"inxh; INcrementeXtended register. This instruction will be used to add 1 to the present content of the rp0DF8 : 22 28 B7""( "shldXB728; Store HLpair using Direct addressing in memory location0DFB : 2B"+"dcxh0DFC : 7E"~"mova,m; Carriage Return (OxD) loaded into A register or Line Feed.0DFD : C9" "ret; ~~~~~~~~~ End of sub-routine ~~~~~~~~~~~~~~~~~~L0DB7I think this converts next character (i.e. number) to integer. e.g. 37 Hex is 7, subtracting 30 hex from it becomes 7.Code:0DB7L0DB7:; ########### Converts a hexadecimal number to a number?? ############0DB7 : D6 30" 0"sui030H; Subtract from accumulator. The command character is in the accumulator.0DB9 : D8" "rc; Return if carry. Not sure what scenario.0DBA : FE 0A" "cpi00AH; ComPare Immediate with Accumulator0DBC : 3F"?"cmc; Complement the carry flag.0DBD : C9" "ret; Returns here if "W2,", "N2," in command string.Thanks!

author: Dom87
author_rank: Contributor
timestamp: July 27, 2020, 07:18:08 pm
content: Well, I've finally worked out the major bits of it. After muchandIt turns out this is how it works.1. A button is pressed on the panel. The 8279 then stores the value in FIFO encoded 2-key lockout.Meaning the value is DB7 = Ctrl key, DB7 Shift key. DB5 is scan line 2, DB4 scan line 1, DB3 scan line 0 and DB2 to DB0 are the key value in an encoded format.It means that in my case, the entire keyboard is in the range of C3 - F7 (converting binary to hexadecimal).2. The main program loops round but continuously checks the FIFO ram. If there is something in memory it is read at address 0510. It then uses a lookup table at 075D.So for example, F1 then becomes 2F at 07BE. 40 signifies that the feature is unavailable or not used.3. I believe it then raises various software interrupts, but mainly RST 3 to perform another lookup based on the mapped value (e.g. 2F) to set the program counter and arrive at a specified address.The table I uploaded before, as shown below is for validating and mapping GPIB commands (L0C59). The 1st Val column maps to the same values as the keyboard. So where the keyboard maps F1 to 2F. A command starting with the ASCII character 'Z' will map to the same value of 2F. From there it executes the same software interrupts and ends up at the same addresses.The 2nd Value column in the table represents the type of value it can accept.80 seems to be a three digit number.00 is a two digit number.Anything between 02 and 09 are single digit numbers.01 is a value with a suffix. e.g. MV, V, KHZ, HZ.What a learning curve!