Ooops. I just realized that I should have pointed out that in the example code, the pull ups should be on the LEAST Significant four bits, not the most significant four as I indicated in the original note. myke Hi Ed, I've copied my reply to the PICList simply because I think there are some points here that would be relavent to other people. >I recently purchased your book and I think you did an great job. >You covered the PIC material well, gave insight on how to use developing >tools. You didn't miss a thing. I only wish I would have found your >book before I bought both PIC'n books. I'm glad you enjoyed the book and found it complete. > I am a second year computer engineering student, and so I have an >understanding of programming in "C" and Motorola assembly. But I still >have many misunderstanding with the PIC code. In school the Motorola >assembly was so simple and straight forward. For example, your code for >the keyboard interface(prog40) uses basically the same hardware set up >as a project I did in school. I used a 4 x 4 keypad and a look-up table >also. I also used a delay for debounce. But my code basically sampled >first the columns, then the rows. Then ORED the two values together to >form a key-code. The look-up table consisted of 32 bytes plus a null >value. The odd table values were key-codes and the even table values >were return data. Then my program looked at each odd value for a match >in the table and skipped over the return data if there was no match. >Does this seem feasible to do on a PIC and if so why doesn't anyone use >it? The Motorola assembly for this code was under 60 line long even >with the data table. If this is not feasible, please explain how your >program(40) looks-up, matches and returns the correct value. When you say "Motorola", I am presuming you are talking about a Motorola 68HCxx device, which is truly Von Neumann and is what is often taught in the schools for introductory assembler programming. There are a lot of excellent texts on this and I find that most instructors are very familiar with how they are programmed. The PIC is a completely different beast all together because it is "Harvard" Architecture. A very efficient program in the PIC can be just about impossible to understand what is happening. The PIC is more of an industry standard archtitecture (as opposed to achedemia) and there are fewer resources and trained instructors - which is a pity because there are some real advantages to the Harvard Architecture for small devices like microcontrollers. When I read your paragraph above, I think we did things pretty similarly, but there are a few differences. The biggest difference is, I used a full keyboard and not a 4x4 keypad. This will cause huge differences in the code (as I will show below). As well, in my code, I support multiple keys pressed at the same time. I outlined the algorithm I used in PROG40 in figure 9-25, but I guess I should have been clearer on what happens when I scan the column. If I find a row that doesn't have all high bits, I set the "KeyPreviously" to the Column. Lastly, the PIC and the 68HCxx devices are radically different devices, as I said above and this drastically affects how the code works. To bring the PIC and 68HCxx into line, here is an example of how I could read a 4x4 keypad with a PIC. I would use an 8 bit port for the interface, which had pull ups on the most significant four lines (which were set to output) and the tristatable Bits on the least significant four lines set to input (which read the columns for the selected row). In the PIC, I could accomplish this with the code below (assuming that "KeyColumn" was defined as the port (PORTB in this example), "Save" and "Count" were defined as bytes): KeyLoop: ; Come Back Here when Key Reset movlw 0x0FF ; Reset the KeyColumn movwf PORTB Loop ; Loop Here Continuously ; #### - Put in Delay Here incf PORTB, w ; Is KeyColumn == 0x0FF == -1 btfss STATUS, Z goto CheckScan ; It's not, Check for the Next Byte bcf PORTB, 4 ; PORTB = 0x0EF to Start the Scan ScanLoop ; Loop Here movlw 1 ; See if the Lower 4 Bits are Still Set addwf PORTB, w ; If they Are, the DC Flag will be Set btfsc STATUS, DC ; Do we Have all 4 Bits Set goto NoScan ; Yes, Loop Around Again movf PORTB, w ; Save the Value for Checking movwf Save clrf Count ; Reset the Count Value goto Loop ; Now, Keep Polling NoScan ; Nothing, Loop Around Again? btfss PORTB, 7 ; Is the High Bit Reset? goto KeyLoop ; Yes, Skip Over bsf STATUS, C ; Set the Carry Flag rlf PORTB ; Shift Through PORTB goto ScanLoop CheckScan ; Check to See if the Scan is the Same movf Save, w ; Still have the Same Value in "Save"? xorwf PORTB, w btfss STATUS, Z ; If Zero Set, then the Same goto KeyLoop ; Not the Same, Start Polling Over incf Count ; Have we Loop 4x yet? btfss Count, 2 goto Loop ; Nope ; #### - Convert the Value in PORTB to a 4 bit number for the Keystroke goto KeyLoop This code takes up 27 instructions to read a 4x4 matrix keyboard on PORTB. "Dlay" should be 5-7 msecs and the conversion routine can be a table although I would probably figure out the value arithmetically. Could you compare your 68HCxx example after taking out the delay routine and the character conversion routines. I'll bet the PIC code is a lot shorter. You gave the measurement of 60 lines of code, I would be interested in the number of instructions. Comparing this snippet to your code is much more appropriate than comparing PROG40 to your code. Now, this might seem like a bit of an artificial example designed to make the PIC look better, but I would argue that you should be designing your application around making the code and wiring as simple as possible. This code takes advantage of a number of features of the PIC that are not necessarily available in the 68HCxx (although many of them are). By the same token, you could design your hardware to be more in line with the 68HCxx architecture for the compare. Note that I use PORTB as the "KeyCount" variable and when I shift or use it, I simply access it like a register variable. I also assume that PORTB can be pulled up. I used the least significant four bits of PORTB as the column read because I know that adding 1 to them would set the Digit Carry Flag if they are still high (ie no button pressed). You should also note that I use "Count" as a variable, but only check bit 2, which indicates that "Count" is equal to four (after the increment). I'm not sure if I've answered your question or not or confused you even more. I guess your question about the validity of using your algorithm for the PIC is answerable with a "Yes". My code above works slightly differently because I take advantage of using a single port for the Drivers and Receivers and using it to keep track of the current scan code. Rather than worrying about what you understand and don't understand about the PIC compared to what you know with other architectures, try to understand the architecture and what can be done with it. This is why I tried building up the architecture in the book, so that you can get an idea of how the PIC works and then writing applications from this understanding. Don't look at it from the perspective of the Motorola architecture and try to translate what is done in the 68HCxx and apply it to PIC code, instead, look at it from the high level and then try to figure out how to do something in the PIC. I realize that this is pretty Zen, but it really is the best way to learn the PIC (and actually any processor architecture) and be able to program in it efficiently. myke "If people don't know what you're doing, they don't know what you're doing wrong." - Sir Humphrey Appleby K.C.B