![]() |
Forum Index : Microcontroller and PC projects : Keyboard for Micromite Plus
![]() ![]() ![]() ![]() |
|||||
Author | Message | ||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
RESULT: ![]() This result is from typing QWERTYUIOP CURRENT CODE: Dim Lookup(8) as string * 8 Lookup(0) = "abcdefgh" Lookup(1) = "ijklmnop" Lookup(2) = "qrstuvwx" Lookup(3) = "yz123456" Lookup(4) = "7890-=[]" Lookup(5) = "\;',./~!" Lookup(6) = "@#$%^&*(" Lookup(7) = ")_+{}|:" + CHR$(34) Lookup(8) = "<>?ABCDE" C0=15:C1=16:C2=17:C3=21:C4=22:C5=23:C6=24:C7=26 'Setup columns R0=02:R1=03:R2=04:R3=05:R4=06:R5=07:R6=09:R7=10:R8=25 'Setup rows SetPin C0,din,pullup:SetPin C1,din,pullup:SetPin C2,din,pullup SetPin C3,din,pullup:SetPin C4,din,pullup:SetPin C5,din,pullup SetPin C6,din,pullup:Setpin C7,din,pullup Setpin R0,dout:SetPin R1,dout:SetPin R2,dout:SetPin R3,dout SetPin R4,dout:SetPin R5,dout:SetPin R6,dout:Setpin R7,dout Setpin R8,dout Delay = 50 DebounceDelay = 10 DEBUG = 0 'MAIN Do SetRow(-1) PAUSE Delay If ReadColumns() <> 255 then print ScanMatrix$(); endif Loop SUB SetRow(value) 'Row pins 2,3,4,5,6,7,9,10,25 if value = -1 then 'Set all bits to 0. This will allow detecting any keypress PORT(2,6,9,2,25,1) = 0 else 'Set a bit to 0 PORT(2,6,9,2,25,1) = 511 - (2 ^ value) endif END SUB FUNCTION ReadColumns() LOCAL FirstScan, ScanCode 'Read the column port and do a simplistic debounce 'Column pins 15,16,17,21,22,23,24,26 FirstScan = PORT(15,3,21,4,26,1) PAUSE DebounceDelay ScanCode = PORT(15,3,21,4,26,1) If FirstScan <> ScanCode then ScanCode = 255 ReadColumns = ScanCode END FUNCTION FUNCTION ScanMatrix$() LOCAL K$,Keys$, RowNumber, ScanCode Keys$ = "" RowNumber = 0 Do SetRow(RowNumber) ScanCode = ReadColumns() 'Decode the ScanCode if ScanCode <> 255 then 'One or more keys were pressed if DEBUG = 1 then PRINT ScanCode for ColumnNumber = 0 to 7 'Check every bit in the column if (Scancode and (2 ^ ColumnNumber)) = 0 then if CAP = 0 AND SFT = 0 then K$ = MID$(Lookup(RowNumber), ColumnNumber + 1, 1) else 'For now use the same lookup table, use RowNumber + 9 when debugged K$ = MID$(Lookup(RowNumber), ColumnNumber + 1, 1) endif if DEBUG = 1 then PRINT str$(RowNumber) + "," + str$(ColumnNumber) + "=>" + K$ endif Keys$ = Keys$ + K$ endif next endif RowNumber = RowNumber + 1 Loop until RowNumber > 8 ScanMatrix$ = Keys$ END FUNCTION Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
This should make qwertyuio work. The location of the P i can not deduct because it is displayed differently. (Probably teraterm character set) [code] Lookup(0) = "abcdeegh" '"abcdefgh" Lookup(1) = "ijklmnop" '"ijklmnop" Lookup(2) = "qrstuqwx" '"qrstuvwx" Lookup(3) = "yz123w56" '"yz123456" Lookup(4) = "7890-=[]" '"7890-=[]" Lookup(5) = "\;',tr~!" '"\;',./~!" Lookup(6) = "@#$%yi*(" '"@#$%^&*(" Lookup(7) = ")_+{}o:" + CHR$(34) '")_+{}|:" + CHR$(34) Lookup(8) = "<>?ABuDE" '"<>?ABCDE" [/code] Each key will print a row and column. That would help with filling the right values in the lookup table. Each row is the index in the array and each column is the position in the string. Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
RESULT: ![]() I don't have any diodes in this matrix, and my lengthy IF/THEN code only looks at one column at a time, so multipule keys have no effect or don't hurt the chip, they are just ignored. I could add some diodes if you wanted me to test this bit too, TZA.... CURRENT CODE: Dim Lookup(8) as string * 8 Lookup(0) = "abcdeegh" '"abcdefgh" Lookup(1) = "ijklmnop" '"ijklmnop" Lookup(2) = "qrstuqwx" '"qrstuvwx" Lookup(3) = "yz123w56" '"yz123456" Lookup(4) = "7890-=[]" '"7890-=[]" Lookup(5) = "\;',tr~!" '"\;',./~!" Lookup(6) = "@#$%yi*(" '"@#$%^&*(" Lookup(7) = ")_+{}o:" + CHR$(34) '")_+{}|:" + CHR$(34) Lookup(8) = "<>?ABuDE" '"<>?ABCDE" C0=15:C1=16:C2=17:C3=21:C4=22:C5=23:C6=24:C7=26 'Setup columns R0=02:R1=03:R2=04:R3=05:R4=06:R5=07:R6=09:R7=10:R8=25 'Setup rows SetPin C0,din,pullup:SetPin C1,din,pullup:SetPin C2,din,pullup SetPin C3,din,pullup:SetPin C4,din,pullup:SetPin C5,din,pullup SetPin C6,din,pullup:Setpin C7,din,pullup Setpin R0,dout:SetPin R1,dout:SetPin R2,dout:SetPin R3,dout SetPin R4,dout:SetPin R5,dout:SetPin R6,dout:Setpin R7,dout Setpin R8,dout Delay = 50 DebounceDelay = 10 DEBUG = 0 'MAIN Do SetRow(-1) PAUSE Delay If ReadColumns() <> 255 then print ScanMatrix$(); endif Loop SUB SetRow(value) 'Row pins 2,3,4,5,6,7,9,10,25 if value = -1 then 'Set all bits to 0. This will allow detecting any keypress PORT(2,6,9,2,25,1) = 0 else 'Set a bit to 0 PORT(2,6,9,2,25,1) = 511 - (2 ^ value) endif END SUB FUNCTION ReadColumns() LOCAL FirstScan, ScanCode 'Read the column port and do a simplistic debounce 'Column pins 15,16,17,21,22,23,24,26 FirstScan = PORT(15,3,21,4,26,1) PAUSE DebounceDelay ScanCode = PORT(15,3,21,4,26,1) If FirstScan <> ScanCode then ScanCode = 255 ReadColumns = ScanCode END FUNCTION FUNCTION ScanMatrix$() LOCAL K$,Keys$, RowNumber, ScanCode Keys$ = "" RowNumber = 0 Do SetRow(RowNumber) ScanCode = ReadColumns() 'Decode the ScanCode if ScanCode <> 255 then 'One or more keys were pressed if DEBUG = 1 then PRINT ScanCode for ColumnNumber = 0 to 7 'Check every bit in the column if (Scancode and (2 ^ ColumnNumber)) = 0 then if CAP = 0 AND SFT = 0 then K$ = MID$(Lookup(RowNumber), ColumnNumber + 1, 1) else 'For now use the same lookup table, use RowNumber + 9 when debugged K$ = MID$(Lookup(RowNumber), ColumnNumber + 1, 1) endif if DEBUG = 1 then PRINT str$(RowNumber) + "," + str$(ColumnNumber) + "=>" + K$ endif Keys$ = Keys$ + K$ endif next endif RowNumber = RowNumber + 1 Loop until RowNumber > 8 ScanMatrix$ = Keys$ END FUNCTION Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
When you press a key you can connect two rows together. If one of them is 1 and the other is 0 then you have a short. Only way to prevent that is to have all pins except the current row as input. That should work without diodes. Your code and mine does not do that so you need to add diodes. It needs a change in code to prevent the shorts if no diodes are used. Did you try some values for the delay and DebounceDelay. You should be able to 'tune' it so that it does not report false key presses. EDIT: You can change the SetRow subroutine to set all the rows to input except the row that is being scanned. This will allow the use of the matrix without diodes. I am not sure what the effect is for the chip. Normally switching all the time between input and output is not done. In this case it happesn only when a key is pressed not when it is 'idle' waiting for a key. [code] SUB SetRow(value) 'Row pins 2,3,4,5,6,7,9,10,25 if value = -1 then Setpin R0,dout:SetPin R1,dout:SetPin R2,dout:SetPin R3,dout SetPin R4,dout:SetPin R5,dout:SetPin R6,dout:Setpin R7,dout Setpin R8,dout 'Set all bits to 0. This will allow detecting any keypress PORT(2,6,9,2,25,1) = 0 else Setpin R0,din,pullup:SetPin R1,din,pullup:SetPin R2,din,pullup SetPin R3,din,pullup:SetPin R4,din,pullup:SetPin R5,din,pullup SetPin R6,din,pullup:Setpin R7,din,pullup Setpin R8,din SELECT CASE value CASE 0 Setpin R0,dout: Pin R0 = 0 CASE 1 Setpin R1,dout: Pin R1 = 0 CASE 2 Setpin R2,dout: Pin R2 = 0 CASE 3 Setpin R3,dout: Pin R3 = 0 CASE 4 Setpin R4,dout: Pin R4 = 0 CASE 5 Setpin R5,dout: Pin R5 = 0 CASE 6 Setpin R6,dout: Pin R6 = 0 CASE 7 Setpin R7,dout: Pin R7 = 0 CASE 8 Setpin R8,dout: Pin R8 = 0 END SELECT endif END SUB [/code] When the pin numbers are in an array the source will be a bit shorter.If this works then can add that. Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
I am testing your code TZA, but my very old-school IF/THEN code should not be able to put shorts where they are not wanted. Using your 8 x 9 chart, when my IF/THEN code polls row1, it is putting a digital 1 on rows 01, 04 and 14 at the same time - a short across ROWS, but they are all outputs, and all on the same common output at any one time. Polling across the columns then finds the key. As each set of rows are set high, polled, then set low again, this should prevent any nasty multi-keypresses from happening, I would have thought, unless I am not seeing something in my head as to the logic of what actually happens with multiple keypresses. ...that would not be a first for me... ![]() ![]() The keyboard matrix itself also has some native resistance in the area of 50R through to 250R or so, which should act as a sort of crude current limiting to some extent, under a fault condition - hope, hope.... ![]() EDIT: This is my last post for tonight - I need sleep. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Pardon my skills with paint but here is what happens: As you can see one key is no problem, two keys on different rows is. Last picture two keys on the same row is also not a problem. ![]() The only way in hardware for Row1 to not short with Row2 is to add a diode. In software you can however switch all rows except the one you are scanning to an input. Then there is only one output on the whole matrix and everything else is an input (rows and columns). You read only the column so having the rows as an input does not really matter for decoding. You don't want the smoke to get out. ![]() ![]() Microblocks. Build with logic. |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Here is a version that does not need diodes for multiple key presses. It uses open collector outputs and these go into high impedance when the pin is a 1. I also cleaned up the code and optimized it to use less space. edit: i found a better way to handle shift,ctrl etc.. code follows soon.... edit again: here it is. (Still untested as i do not have a MM+ yet) [code] 'This version allows for more key presses at the same time 'without adding diodes. 'It sets all rows to OC (Open Collector) outputs 'All inputs are pulled high internally. '72 characters in a lookup string 123456789012345678901234567890123456789012345678901234567890123456789012 'for locating the right position "abcdefghijlkmnopqrstuvwxyz1234567890-=[]\;',./~!@#$%^&*()_+{}|:<>?ABCDEF" DIM Lookup LENGTH 72 AS STRING= "abcdefghijlkmnopqrstuvwxyz1234567890-=[]\;',./~!@#$%^&*()_+{}|:<>?ABCDEF" 'Define the pins that are used for the Rows DIM integer Rows(8) = (2,3,4,5,6,7,9,10,25) 'Define the pins that are used for the columns DIM integer Cols(7) = (15,16,17,21,22,23,24,26) DIM Delay = 50, DebounceDelay = 10 DIM DEBUG = 1 DIM RAWMODE = 0 'If RAWMODE = 1 then unmodified values will be send 'We can use A-Z for the modifiers and special keys. CONST CSHIFTL = ASC("L"), CSHIFTR = ASC("R"), CCAPS = ASC("C"), CFN = ASC("F") CONST CCONTROL = ASC("O"), COPTION = ASC("P"), CCOMMAND = ASC("M") CONST CTAB = ASC("T"), CDEL = ASC("D"), CENTER = ASC("E") CONST CUP = ASC("W"), CLEFT = ASC("A"), CRIGHT = ASC("D"), CDOWN = ASC("S") DIM CAPSMODE = 0 'Setup all rows as output with open collector For i = 0 to 8 Setpin Rows(i),dout,OC next 'Setup all columns as input with a pullup For i = 0 to 7 Setpin Cols(i),din,pullup next 'MAIN Do PAUSE Delay print ScanMatrix$(); Loop SUB SetRow(value) if value = -1 then 'Set all bits to 0. This will allow detecting any keypress PORT(2,6,9,2,25,1) = 0 else 'Set a bit to 0 PORT(2,6,9,2,25,1) = 511 - (2 ^ value) endif END SUB FUNCTION ReadColumns() LOCAL FirstScan, ScanCode 'Read the column port and do a simplistic debounce 'Column pins 15,16,17,21,22,23,24,26 FirstScan = PORT(15,3,21,4,26,1) PAUSE DebounceDelay ScanCode = PORT(15,3,21,4,26,1) If FirstScan <> ScanCode then ScanCode = 255 ReadColumns = ScanCode END FUNCTION FUNCTION ScanMatrix$() LOCAL K$,Keys$, RowNumber, ScanCode Keys$ = "" '-1 is as Special case! This allows to read the 'whole matrix to see if a key is pressed 'If one bit in the column is low (0) then 'a key has been pressed and scanning can start. RowNumber = -1 Do SetRow(RowNumber) ScanCode = ReadColumns() If RowNumber = -1 and ScanCode = 255 then 'if no key was pressed there is no need to scan EXIT FUNCTION endif 'Decode the ScanCode if ScanCode <> 255 then 'One or more keys were pressed if DEBUG = 1 then PRINT ScanCode for ColumnNumber = 0 to 7 'Check every bit if it is 0 in the scanned row if (Scancode and (2 ^ ColumnNumber)) = 0 then P = RowNumber * 8 + ColumnNumber + 1 K$ = MID$(Lookup, P, 1) if DEBUG = 1 then PRINT "M:" + str$(M) + "R:" + str$(RowNumber) + " C:" + str$(ColumnNumber) + " P:" + str$(P) + " =>" + K$ endif Keys$ = Keys$ + K$ endif next endif RowNumber = RowNumber + 1 Loop until RowNumber > 8 if RAWMODE = 0 then ScanMatrix$ = ModifyKeys$(Keys$) else ScanMatrix$ = Keys$ endif END FUNCTION FUNCTION ModifyKeys$(values$) LOCAL modvalues$, modifiers$ 'split values$ into modifiers and normal keys for i = 1 to len(values$) c = ASC(MID$(values$,i,1)) if c >= 65 and c <= 90 then 'check for modifiers or special keys modifiers$ = modifiers$ + CHR$(c) else modvalues$ = modvalues$ + CHR$(c) endif next 'Check for left or right shift for i = 1 to len(modifiers$) c = ASC(MID$(values$,i,1)) SELECT CASE c CASE CSHIFTL, CSHIFTR modvalues$ = UCASE$(modvalues$) 'CASE CFN 'Handle the FN key 'etc... END SELECT next if DEBUG = 1 and modvalues$ <> values$ then print " IN:" + values$ + " OUT:" + modvalues$ endif ModifyKeys$ = modvalues$ END FUNCTION [/code] If we can make this work then it is time to add Shift,Ctrl, Fn, etc combinations. Ctrl+Alt+Del anyone? edit: worked on the code a bit more and setup a structure that allows adding the key modifiers. Also added a RAWMODE so that unmodified character codes are send. This will allow programs to use for instance the left and right shift keys (good for a pinball game ![]() Once the lookup string has all the right characters it will not have any capital letters. We can then use A-Z for the modifiers and special keys. The way the scan works is that when for example the left shift key is pressed it will return a "L". When the next key is pressed. Maybe a "a" then the values$ will have "aL" or "La". So you do not need to remember the modifiers. They are available each call. CAPS LOCK is special, because when it is released it still needs to be remembered. Not figured out the best way to do that yet. If we want to use this keyboard to be able to edit a program, then we need to know what has to be send when function keys, arrows, etc are used. Does somebody have a table with those values? Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
UPDATE: ![]() I should mention that I am not using the MM+ for any of this testing, I am just using a standard 170 MM, as that is what I am going to use in the replacement PCB. Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
I was thinking long about that line. The manual is not clear about the syntax at all. The part before the = can i think also be: [code] Dim Lookup as string * 72 [/code] Which version of MM are you using? Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
See the last sentence of my previous post. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
I used the manual from 4.7 Beta. So the used command/functions should work. The syntax of the DIM is confusing so i goofed that one up. Unfortunately do not have a 4.7 Beta DOS version (does not exist i think) so i can not test my syntax. If all goes well i have some chips tomorrow. Can you tell me which pins are connected to which column/row so i can use the same configuration. Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
Here is how I have my rows and columns setup: '================================= 'CONFIGURE COLUMN, ROW & LED PINS: '================================= C1=26:C2=24:C3=23:C4=22:C5=17:C6=16:C7=15:C8=21 'Column pins R1=06:R2=04:R3=05:R4=02:R5=07:R6=09:R7=25:R8=03:R9=10 'Row pins PWR=14:CAPS=18 'LED pins DELAY=100 'Key repeat delay in ms Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Should i read that as: R1 pin 6 on the PIC and the first row in the matrix pins 01,04 and 14. and C1 pin 26 on the PIC and the first column from the matrix pin 15. and so on... Is that correct? Microblocks. Build with logic. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
Correct. Sorry if that was not clear. ![]() Here is a bit more of the code, so you can see what I am doing: '================================= 'CONFIGURE COLUMN, ROW & LED PINS: '================================= C1=26:C2=24:C3=23:C4=22:C5=17:C6=16:C7=15:C8=21 'Column pins R1=06:R2=04:R3=05:R4=02:R5=07:R6=09:R7=25:R8=03:R9=10 'Row pins PWR=14:CAPS=18 'LED pins DELAY=100 'Key repeat delay in ms setpin PWR,dout:setpin CAPS,dout SetPin C1,dout:Pin(C1)=0:SetPin C2,dout:Pin(C2)=0:SetPin C3,dout:Pin(C3)=0 SetPin C4,dout:Pin(C4)=0:SetPin C5,dout:Pin(C5)=0:SetPin C6,dout:Pin(C6)=0 setpin C7,dout:pin(C7)=0:setpin C8,dout:pin(C8)=0:SetPin R1,din,pulldown SetPin R2,din,pulldown:SetPin R3,din,pulldown:SetPin R4,din,pulldown SetPin R5,din,pulldown:SetPin R6,din,pulldown:setpin R7,din,pulldown setpin R8,din,pulldown:setpin R9,din,pulldown Smoke makes things work. When the smoke gets out, it stops! |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6266 |
I think there is a bug in MM Basic. Try a space between STRING and = DIM Lookup LENGTH 72 AS STRING = "abcdefghijlkmnopqrstuvwxyz1234567890-=[]\;',./~!@#$%^&*()_+{}|:<>?ABCDEF"
Jim VK7JH MMedit |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9586 |
Yes, when I try that, the code does progress much further to this point: ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
The reason i went with the PIC16F1459is that i want to make an as small as possible generic Matrix to Serial module you can see in the picture. I have overlayed it on the picture to get a feel for the size. ![]() By being this small it should fit in most keypads and it will use only one of the precious mcu pins. With a micromite it can then even be used as a noraml keyboard so that programming will be very easy using normal inkey$ and inputstatements. Allowing you to fully test the program with Teraterm first. This module is one of the hopefully many i have planned for my long overdue 'MicroBlocks'. I had to think about a whole new concept to use these modules as the market is floodedwith 'modules' and i think i have found a nice niche. More on that later. Goes by the "BBM Series" codename. (Each product should have a codename ![]() ![]() Microblocks. Build with logic. |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
G, I will check the code for that error. Ok. Found it. Change [code] 'Decode the ScanCode if ScanCode <> 255 then [/code] to [code] 'Decode the ScanCode if DEBUG = 1 then PRINT RowNumber; if RowNumber >= 0 and ScanCode <> 255 then [/code] Microblocks. Build with logic. |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6266 |
That error suggests that 'P" is negative or zero. DIM Lookup LENGTH 72 AS STRING = "abcdefghijlkmnopqrstuvwxyz1234567890-=[]\;',./~!@#$%^&*()_+{}|:<>?ABCDEF"
FOR P = 1 TO 74 k$= MID$(Lookup, P, 1) PRINT P," *",k$,"*" NEXT P P=0 k$= MID$(Lookup, P, 1) PRINT P," *",k$,"*" I don't have a keyboard to play with. Jim VK7JH MMedit |
||||
paceman Guru ![]() Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
Wow, that is small TZ, less than an inch across, (oops, < 2.54mm). If you can get this flying there should be plenty of takers - the biggest problem will be fitting a socket for it - the cable that is. Greg |
||||
![]() ![]() ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |