Shop OBEX P1 Docs P2 Docs Learn Events
calculator input?! — Parallax Forums

calculator input?!

ohVaNiLLaGoRiLLaohVaNiLLaGoRiLLa Posts: 33
edited 2013-04-19 17:16 in BASIC Stamp
im trying to use a matrix keypad for user input for a calculator using a basic stamp 2 micro controller. I am having issues getting my code to store the button pressed and then putting them all together. So lets say someone wanted to enter the number 25. the program has to store the 2 and the 5 as variables and then multiply the 2 by 10 and add 5. pretty strait forward but looping this is difficult since the keypad outputs what seems to be zero when nothing is pressed. so my variables just become zeros >____< I only need to get a max 3 digits since this is going to be used for an 8 bit calculator...


I believe I just have to use some if then statements and some do loop statements... anyone have any ideas? ive googled this too but to no avail.

' {$STAMP BS2}
' {$PBASIC 2.5}


row         VAR  Nib                        ' Variable space for row counting
column      VAR  Nib                        ' Variable space for column counting
keypad      VAR  Word                       ' Variable space to store keypad output
keypadOld   VAR  Word                       ' Variable space to store old keypad output
temp        VAR  Nib                        ' Variable space for polling column states
keynum      VAR  Word                       ' Variable for keystroke
placeholder        VAR  Nib                        ' Variable for keeping track of digit placement
ks1         VAR  Nib                        ' variable for 1st keystroke
ks2         VAR  Nib                        ' variable for 2nd keystroke
ks3         VAR  Nib                        ' variable for 3rd keystroke
finalnum    VAR  Nib                        ' variable for final number output


placeholder = 0
DO
  GOSUB readkeypad
  GOSUB display


  IF keypad <> keypadold THEN
    GOSUB placedigit
  ENDIF


  IF keynum = "A" OR "B" THEN
    GOSUB compile
  ENDIF
LOOP


' -----[ Subroutine - compile ]-------------------------------------------------
compile:
  IF placeholder = 0 THEN finalnum = ks1
  IF placeholder = 1 THEN finalnum = ks1 * 10 + ks2
  IF placeholder = 2 THEN finalnum = ks1 * 100 + ks2 * 10 + ks3
  DEBUG DEC ? finalnum, CR
  DEBUG BIN ? finalnum, CR
RETURN




' -----[ Subroutine - Placedigit ]-------------------------------------------------
placedigit:
  IF placeholder = 2 THEN ks3 = keynum
  IF placeholder = 1 THEN
  ks2 = keynum
  placeholder = 2
  ENDIF
  IF placeholder = 0 THEN
  ks1 = keynum
  placeholder = 1
  ENDIF
RETURN




' -----[ Subroutine - ReadKeypad ]-------------------------------------------------
' Read keypad button states
readkeypad:
  keypad = 0
  OUTL   = 000000                        ' Initialize IO
  DIRL   = 000000


  FOR row = 0 TO 3
    DIRB = 11                            ' Set columns (P7-P4) as outputs
    OUTB = 00                            ' Pull columns low (act as pull down)
    OUTA = 1 << Row                         ' Set rows high one by one
    DIRA = 1 << Row


    temp = 0                                ' Reset temp variable to 0
    FOR column = 0 TO 3
      INPUT (column + 4)                    ' Set columns as inputs one by one
      temp = temp | (INB & (1 << column))   ' Poll column state and store in temp
    NEXT


    keypad = keypad << 4 | (Temp REV 4)     ' Store keypad value
  NEXT
RETURN


' -----[ Subroutine - Display ]----------------------------------------------------
' sets numbers
display:
  IF Keypad.bit15 THEN  keynum = 1
  IF Keypad.BIT14 THEN  keynum = 2
  IF Keypad.BIT13 THEN  keynum = 3
  IF Keypad.BIT12 THEN  keynum = "A"
  IF Keypad.BIT11 THEN  keynum = 4
  IF Keypad.BIT10 THEN  keynum = 5
  IF Keypad.BIT9  THEN  keynum = 6
  IF Keypad.BIT8  THEN  keynum = "B"
  IF Keypad.Bit7  THEN  keynum = 7
  IF Keypad.Bit6  THEN  keynum = 8
  IF Keypad.Bit5  THEN  keynum = 9
  IF Keypad.Bit4  THEN  keynum = "C"
  IF Keypad.Bit3  THEN  keynum = "*"
  IF Keypad.Bit2  THEN  keynum = 0
  IF Keypad.BIT1  THEN  keynum = "#"
  IF Keypad.Bit0  THEN  keynum = "D"
RETURN

this is what im trying to use but it keeps going to the gosub compile.... without a or b being pressed..... :[

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-18 19:09
    Usually with a calculator, the digits are acted on immediately as well as any command keys. The full numeric value is accumulated into an accumulator (a word in the case of a Stamp) like this:

    accumulator = accumulator * 10 + keynum

    keynum is a value from 0 to 9 representing the numeric key just pressed.

    If you want a backspace or remove digit command key, you'd do:

    accumulator = accumulator / 10

    In your "display" routine, what's the value of keynum if Keypad is all zero bits.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-18 19:10
    Usually with a calculator, the digits are acted on immediately as well as any command keys. The full numeric value is accumulated into an accumulator (a word in the case of a Stamp) like this:

    accumulator = accumulator * 10 + keynum

    keynum is a value from 0 to 9 representing the numeric key just pressed.

    If you want a backspace or remove digit command key, you'd do:

    accumulator = accumulator / 10

    In your "display" routine, what's the value of keynum if Keypad is all zero bits?
  • ercoerco Posts: 20,257
    edited 2013-04-18 21:19
    Excellent advice from my forum hero Mike on inputting the digits. Sounds like you just have the hardware issue of decoding the keypad. After that, you're on your way.

    IMO, writing a calculator program is a great coding exercise. I thoroughly enjoyed programming a simple talking calculator using a computer keyboard and integer math on "another processor": http://www.youtube.com/watch?v=624cmIr5qBs&feature=player_detailpage#t=28s

    Later, I found this nifty talking calculator on Ebay for $9 and just had to have it: http://www.ebay.com/itm/250976474687
  • ohVaNiLLaGoRiLLaohVaNiLLaGoRiLLa Posts: 33
    edited 2013-04-19 13:19
    @mike green
    wow i knew there was an easier way to do it! i have much better code now but i am having an issue with that its doing the accumulator thing twice....

    here is the code i am now using
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    
    row         VAR  Nib                        ' Variable space for row counting
    column      VAR  Nib                        ' Variable space for column counting
    keypad      VAR  Word                       ' Variable space to store keypad output
    keypadOld   VAR  Word                       ' Variable space to store old keypad output
    temp        VAR  Nib                        ' Variable space for polling column states
    keynum      VAR  Word                       ' Variable for keystroke
    accumulator VAR Word
    
    
    
    
    
    
    DO
      GOSUB readkeypad
    
    
      IF keypad <> keypadold THEN
        GOSUB display
          IF keynum <> "C" THEN
            accumulator = accumulator * 10 + keynum
            keypadold = keypad
            DEBUG DEC  accumulator, CR
            PAUSE 500
          ELSE
            DEBUG CLS
          ENDIF
      ENDIF
    LOOP
    
    
    
    
    ' -----[ Subroutine - ReadKeypad ]-------------------------------------------------
    ' Read keypad button states
    readkeypad:
      keypad = 0
      OUTL   = %00000000                        ' Initialize IO
      DIRL   = %00000000
    
    
      FOR row = 0 TO 3
        DIRB = %1111                            ' Set columns (P7-P4) as outputs
        OUTB = %0000                            ' Pull columns low (act as pull down)
        OUTA = 1 << Row                         ' Set rows high one by one
        DIRA = 1 << Row
    
    
        temp = 0                                ' Reset temp variable to 0
        FOR column = 0 TO 3
          INPUT (column + 4)                    ' Set columns as inputs one by one
          temp = temp | (INB & (1 << column))   ' Poll column state and store in temp
        NEXT
    
    
        keypad = keypad << 4 | (Temp REV 4)     ' Store keypad value
      NEXT
    RETURN
    
    
    ' -----[ Subroutine - Display ]----------------------------------------------------
    ' sets numbers
    display:
      IF Keypad.BIT15 THEN  keynum = 1
      IF Keypad.BIT14 THEN  keynum = 2
      IF Keypad.BIT13 THEN  keynum = 3
      IF Keypad.BIT12 THEN  keynum = "A"
      IF Keypad.BIT11 THEN  keynum = 4
      IF Keypad.BIT10 THEN  keynum = 5
      IF Keypad.BIT9  THEN  keynum = 6
      IF Keypad.BIT8  THEN  keynum = "B"
      IF Keypad.BIT7  THEN  keynum = 7
      IF Keypad.BIT6  THEN  keynum = 8
      IF Keypad.BIT5  THEN  keynum = 9
      IF Keypad.BIT4  THEN  keynum = "C"
      IF Keypad.BIT3  THEN  keynum = "*"
      IF Keypad.BIT2  THEN  keynum = 0
      IF Keypad.BIT1  THEN  keynum = "#"
      IF Keypad.BIT0  THEN  keynum = "D"
    RETURN
    


    and the debug terminal gives me
    1
    11
    


    i put that pause in attempt to debounce it but that obviously isnt working. why is keypadold not equal to keypad? that must be the issue since it is doing it twice... but why does it stop after just doing it one extra time? no idea......
  • SapphireSapphire Posts: 496
    edited 2013-04-19 13:51
    Because when you release the key, keypad <> keypadold.
  • ohVaNiLLaGoRiLLaohVaNiLLaGoRiLLa Posts: 33
    edited 2013-04-19 14:03
    oh! that makes complete sense!! any idea on how to make that stop... lol
  • SapphireSapphire Posts: 496
    edited 2013-04-19 14:09
    Well, keypad should = 0 when no key is pressed. So only do the conversion/accummulation if keypad <> 0 AND keypad <> keypadold might work.
  • ohVaNiLLaGoRiLLaohVaNiLLaGoRiLLa Posts: 33
    edited 2013-04-19 17:16
    That might actually work! Thanks ill try it in a bit

    edit:
    thank you so much sapphire that worked great!
    and thanks again mike green for getting me started in the right direction! :D
Sign In or Register to comment.