Shop OBEX P1 Docs P2 Docs Learn Events
Working with hex and decimal — Parallax Forums

Working with hex and decimal

KivistoKivisto Posts: 17
edited 2008-11-26 01:16 in BASIC Stamp
Hi guys,

I am currently working with the following code. It is the generic 4x4 matrix keypad software that was printed in Nuts & Volts Column 22, but I have edited it to not only read the keypad, but store the last 3 digits pressed by hitting the # key. The program runs perfectly on my BS2, but my problem lies in the fact that the keypad input is in Hexadecimal format.

I will be adding functionality, which is listed in the second code listing, to subtract 1 from the stored number any time a specific pin on the BS2 goes high. Like I said, this code has been tested and functions exactly how I need it to, with the exception that I need to be working strictly in decimal. As the code stands the number stored is having 1 subtracted every time Pin 4 goes HIGH. However, the 3-digit number being stored in 'code' is a Hexadecimal value. I need to make this happen in decimal for this to be functioning according to specification.

This seems like it could be really simple to fix, but my Basic skills aren't up to snuff. Any suggestions or fixes would be greatly appreciated. Thanks!

DIRS = %100000000000000

code VAR WORD    'The input code is stored in this variable

key_index VAR NIB   'Keeps track of the number of keypresses

debounce VAR BIT

i VAR NIB
l VAR NIB
m VAR NIB
t VAR NIB
time VAR BYTE
index VAR WORD
bit_index VAR NIB
key_press VAR BIT
key VAR NIB
row VAR NIB      'Control lines
columns VAR INC    'Sense lines

init:

  key_index = 0
  FOR i = 0 TO 15     'Intially set the keycode to 000
  code.LOWBIT(i) = 0
  time = 0
  NEXT

start:        'Program starts here

  GOSUB search_key
  IF key_press = 0 THEN start
  DEBUG "key pressed = ", HEX key,CR
  key_press = 0
      GOTO start

search_key:        'Scan the keypad for keypresses
      FOR row = 0 TO 3    'Send the control lines low, one at a time
      LOW row
    key = ~columns  'Check the sense lines (all at once) for key presses
  key = NCD key
  IF key <> 0 THEN push  'If key = 0 then no key was pressed
  time = time + 1

  INPUT row      'Send the control line high
  NEXT

  debounce = 0

  IF (time > 10200) THEN times_up  'If no key has been pressed within the last 30 sec the code will be cleared

  back:  RETURN

push:

  IF debounce = 1 THEN done  'Prevent debouncing
  debounce = 1
  key_press = 1
  key = (key-1) + (row*4)
  LOOKUP key,[noparse][[/noparse]14,0,15,13,7,8,9,12,4,5,6,11,1,2,3,10],key   'Find which key was pressed
  IF (key = 12) THEN clear             'Clear was pressed
  IF (key = 15) AND (key_index <= 2) THEN no_action 'Enter has been pushed but three digits have not been entered.
                    'Go back and search for more inputs.
  IF (key_index >= 3) AND (key = 15) THEN countdown
   'three digits and enter have been pushed so send the data to countdown
  IF (key_index >= 3) THEN shift 'If more than three keys have been pressed need to store the last three entered.
  IF (key = 10) THEN no_action  'A has been pressed - ignore
  IF (key = 11) THEN no_action  'B has been pressed - ignore
  IF (key = 13) THEN no_action  'D has been pressed - ignore

  code.LOWNIB(2-key_index) = key  'Store the entered key

  key_index = key_index + 1  'Keep track of how many keys have been entered

done:

  INPUT row      'Disconnect output on row
      RETURN

clear:

  FOR l = 0 TO 15      'Clear the keycode
  code.LOWBIT(l) = 0
  NEXT
  FOR m = 0 TO 3
  code.LOWNIB(m) = 0
  NEXT
  key_press = 0
  key_index = 0
  index=0
  PAUSE 100
  GOTO search_key
'Shift is a subroutine making sure that the last three keypresses are stored

shift:

  code = (code >> 4)    'Delete the first key entered
  code.LOWNIB(3) = key  'Store the last key entered
  key_index = key_index + 1
  GOTO done


times_up:

  DEBUG "Time is up - Code will be cleared",CR
  time = 0
  FOR t=0 TO 3
  code.LOWNIB(t) = 0
  DEBUG? code.LOWNIB(t)
  key_index = 0
  NEXT
  GOTO back

no_action:

  key_press = 0
  GOTO search_key

send_data:

  DEBUG "keys stored: ", HEX code, CR
  GOTO countdown




countdown:
IF (IN4=1) THEN startcountdown
GOTO countdown

startcountdown:
code = (code - 1)
DEBUG "count: ", HEX code, CR
IF (code=0) THEN complete
DO UNTIL IN4=0
LOOP
GOTO countdown

Complete:
OUT15 =1
DEBUG "COMPLETE", CR

END

Comments

  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2008-11-25 06:22
    Hi Kivisto, numbers in the Stamp are stored as 1's and 0's not decimal octal or hex.

    Hex and decimal are a way of formatting those 1's and 0's for display in a way that makes it easier for us to interpret or formatted in a way that some peripheral device may require.

    Displaying the value you need should be as simple as changing the line DEBUG·"count:·",·HEX·code,·CR to DEBUG·"count:·",·DEC·code,·CR.

    If that does not produce the expected result then the variable "code" has not been stored in the correct manner.

    Jeff T.
  • KivistoKivisto Posts: 17
    edited 2008-11-25 06:57
    I've tried changing the "HEX code" to "DEC code", but it still works incorrectly.
    Say I input 123 on the keypad and store it.
    Instead, the application counts down from 291, which is the decimal equivalent of 123 in HEX.
    I need to be able to input 123, and then countdown from 123 in decimal. Any suggestions? I'm really
    pressed to get this thing working.

    Thanks again!

    Post Edited (Kivisto) : 11/25/2008 8:34:10 AM GMT
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2008-11-25 07:10
    Kivisto -

    What is 123 ? It's 1 x 10^2 + 2 x 10^1 + 3 X 10^0. Get the picture?

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When all else fails, try inserting a new battery.
  • KivistoKivisto Posts: 17
    edited 2008-11-25 07:57
    I understand that 123 is 1 x 10^2 + 2 x 10^1 + 3 x 10^0, yes.
    But I'm sorry, I'm still just not seeing what I need to do specifically to
    make my code do what I need it to do.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2008-11-25 08:25
    Kivisto -

    I apparently misunderstood what the problem was. In any case, that is the method to change 3 single, ordered digits into a 3 digit number. Apparently that was not what was needed - sorry for the confusion.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When all else fails, try inserting a new battery.
  • awesomeduckawesomeduck Posts: 87
    edited 2008-11-25 15:02
    I think Bruce was right, I think you are storing the keystrokes in packed BCD format. What you need to do is convert that to am integer.

    Right before you start the countdown do something like this:

    code = (code.LOWNIB(2) * 100) + (code.LOWNIB(1) * 10) + (code.LOWNIB(0))
  • KivistoKivisto Posts: 17
    edited 2008-11-25 15:06
    Thanks awesomeduck. I'll give that a try and report back.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2008-11-25 15:29
    Kivisto -

    You can call the system that the keypad uses anything you want, but the fact remains that you have a 16 KEY pad. If the keys were numbers, how many could one account for? Yup, 0-9 and six more = 16. Thus the keypad manufacturers (many do it this way) number the keys as follows:

    0-9 are as they appear, but 11 = A, 12 = B, 13 = C, 14 = D, 15 = E and last but not least 16 = F.

    Rather unfortunately, those LOOK like "HEX numbers", so you MUST look at them merely as CHARACTERS. So, you have the characters 0-9 and the characters A-F. Make sense now?

    It's CERTAINLY confusing the first time you get involved with a 4 X 4 keypad. I should add that even a 3 X 4 or 4 X 3 keypad often has the same arrangement in terms of CHARACTERS vs. numbers, but that goes from 0-9, and then A, and B.

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When all else fails, try inserting a new battery.

    Post Edited (Bruce Bates) : 11/25/2008 3:36:54 PM GMT
  • Carl HayesCarl Hayes Posts: 841
    edited 2008-11-25 16:27
    This is fairly simple.· You have a 2-byte variable, code, which contains, for example,·the value $0123.· Considered as a binary number, the decimal equivalent would be 291.· But you intend it to represent the decimal number 123, which would be a hexadecimal value $007B.

    To make the conversion, insert the following just after capturing the number:

    ·· code = code.nib0 + 10*code.nib1 + 100*code.nib2

    and your problem is solved.· My question is, why didn't these other guys just tell you that?



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net

    Post Edited (Carl Hayes) : 11/25/2008 4:33:30 PM GMT
  • awesomeduckawesomeduck Posts: 87
    edited 2008-11-25 16:32
    Carl.... I think we did tell him, exactly that.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2008-11-25 16:43
    Awesomeduck -

    Thank you for that. I wasn't going to be quite as diplomatic as you were. These snide asides are starting to really get to me.

    Regards,

    Bruce Bates

    whose name is readily apparent
    at the end of every post!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When all else fails, try inserting a new battery.
  • Carl HayesCarl Hayes Posts: 841
    edited 2008-11-25 16:44
    Another way to do this, more versatile, would be something like this.· Capture each keypress in a byte· or nib variable, let's call it key.· You want the eventual result in a word variable code.



    ···· Code = 0

    Keyloop:····

    ····· (capture a single keystroke in key)

    ····· IF·· key = (value that represents the pound sign) THEN Keyloopexit

    ···· Code = 10*code + key

    ···· goto Keyloop

    Keyloopexit:

    ··· (whatever)



    The first time through the loop, Code is 0 and you enter "1", so Code now becomes 10*0 + 1 = 1

    The second time through the loop, Code is 1 and you enter "2", so Code now becomes 10*1 + 2 = 12

    The third time through the loop, Code is 12 and you enter "3", so Code now becomes 10*12 + 3 = 123

    The fourth time through the loop, Code is 123 and you enter "#", so·you exit the loop, Code stays 123, and you have a big grin.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net
  • Carl HayesCarl Hayes Posts: 841
    edited 2008-11-25 16:55
    awesomeduck said...
    Carl.... I think we did tell him, exactly that.
    Yes, you did (no one else did, so you could have said I instead of we, except that you're a diplomat), apparently between the time I read the thread [noparse][[/noparse]before my morning exercises]) and the time I posted (after exercises & breakfast).· Sorry.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2008-11-25 18:22
    Because of the left-right order that the Stamp does math, and because the most significant digit is stored in code.nib0, it should probably be,

    code = code.nib0 *10 + code.nib1 *10 + code.nib2  ' left to right without ()
    



    or with (),

    code = (code.nib0 *100) + (code.nib1 *10) + code.nib2
    




    not code = code.nib0 + 10*code.nib1 + 100*code.nib2
    because code.nib2 is not your most significant, and because the Stamp will execute that expression strictly left to right, that is, add 10 to code.nib0, then multiply that total times code.nib1, then add 100 to that, then multiply time code.nib2, which is nonsensical.

    This could be done as part of the key scanning, starting with code=0,

    'code.LOWNIB(2-key_index) = key 'Store the entered key
    code = code *10 + key  'Store the entered key as accumulation
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com

    Post Edited (Tracy Allen) : 11/25/2008 6:27:44 PM GMT
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2008-11-25 18:32
    Carl Hayes said...(trimmed)
    your problem is solved.· My question is, why didn't these other guys just tell you that?
    Carl,

    ·· Let's remember why we're all here.· This is a support forum and·members who are trying to help are doing just that.· They're not getting paid for this, they just do it because they like to help people.· Statements like the one above are not very friendly to the family environment we're going for here.· If you have something to contribute, please do.· But please do it without pointing out what you perceive to be a lack of help from someone else.· Everyone tries to help in their own way.

    ·· I can tell you first hand that generally speaking we don't generally supply exact answers to questions in some cases.· This is because if you just give someone the answer, they don't learn from it.· The typical way is to help them help themselves.· This can sometimes take a little longer, but we find that members learn from the steps taken to arrive at the final solution.· That's not to say that is the situation here, I am just saying sometimes members will pace their information.· And of course everyone has their own way of working things out.· Let's try to respect this please so we can all benefit from what the forums have to offer.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Engineering
  • Carl HayesCarl Hayes Posts: 841
    edited 2008-11-25 18:59
    I'm guessing, Tracy, that you are right, because of the nonstandard way (wihout hierarchy) that the Stamp editor handles arithmetic operators.· The use of parentheses would cure it, as you suggest.· Maybe I'll run an experiment.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net
  • KivistoKivisto Posts: 17
    edited 2008-11-25 19:34
    LOL, didn't mean to have the dramatic thread guys. Regardless, thanks everyone for their help.
    Tracy, I have tried using your suggested code in various places. I'm still not getting it to work out right.
    Can someone suggest a specific location to place that code, or does anyone see something that may need to be changed?
    ·
  • awesomeduckawesomeduck Posts: 87
    edited 2008-11-25 20:24
    I still stand by my original line of code. Despite the "non standard" way that PBASIC parses the following line looks right to me:

    code = (code.LOWNIB(2) * 100) + (code.LOWNIB(1) * 10) + (code.LOWNIB(0))

    The ()'s take care of the order of operations and the LOWNIB indexes nibbles in a word from right to left. HIGHNIB indexes nibbles from left to right.
    At least according to the "Memory Organization and Variables" section of the PBASIC help file.
    As far as where this line of code needs to go in the program, in keeping with the spirit of Chris Savage's post....it needs to go somewhere in your program after the key entry is complete and before you start ticking down the count.

    I'd also like to point out that the method of doing the math at key entry, with "Code = 10*code + key" in the loop also works well.

    Check out the DIG operator for converting a binary value to binary coded decimal. It is pretty handy.
  • KivistoKivisto Posts: 17
    edited 2008-11-25 20:32
    Thanks guys, got it!
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2008-11-25 21:54
    Oh, I see that your original routine did in fact store the value with nib2 as the most significant digit, so awesomeduck is right. I didn't notice the subtraction from 2.

    Another way to write it (with nib2 as most significant) is
    code = code.nib2*10 + code.nib1 *10 + code.nib0
    That is just to show that there are different ways to do the same thing. That would go in as the first instruction in the countdown routine.

    As an alternative, I would replace the line,
    [s]code.LOWNIB(2-key_index) = key  'Store the entered key[/s]
    


    with
    code = code * 10 + key   ' accumulate decimal value of code, starting with code=0
    


    If you do it that way, you can also replace the lines
    [s]IF (key = 15) AND (key_index <= 2) THEN no_action 'Enter has been pushed but three digits have not been entered.
                        'Go back and search for more inputs.
      IF (key_index >= 3) AND (key = 15) THEN countdown[/s]
    


    with
    IF (key_index= 3) OR (key = 15) THEN countdown
    


    That is, if the user presses only 1 or two keys and then ENTER, the routine can branch right to countdown and the value in code will still be correct. So 57 ENTER would be the same as 057 ENTER

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com
  • Carl HayesCarl Hayes Posts: 841
    edited 2008-11-26 01:16
    awesomeduck said...
    I still stand by my original line of code. Despite the "non standard" way that PBASIC parses the following line looks right to me:

    code = (code.LOWNIB(2) * 100) + (code.LOWNIB(1) * 10) + (code.LOWNIB(0))
    You ought to stand by it, because it's correct and will work in almost any parser.· Mine would work in most, and if I had thought to add the parentheses (as you did) it would work in the Stamp parser, too.

    Doesn't matter in which order you give the operands, because addition is perfectly commutative (and so is multiplication).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net
Sign In or Register to comment.