Shop OBEX P1 Docs P2 Docs Learn Events
Need some hand holding with this code... — Parallax Forums

Need some hand holding with this code...

Don MDon M Posts: 1,652
edited 2013-02-19 20:00 in Propeller 1
What I'm trying to do is enter some numbers into a variable and display them on the lcd display. I've been tearing my hair out trying to solve this.

"key" is a byte returned from a touchscreen method. It returns the ascii numbers 0 - 9 ($30 - $39).

On the display (disp) it shows the string- "Enter year (2000 - 2099): " Lets say I want to enter 2013. The display will show 2 then 20 then 201 then 2013 as I type the numbers in. That is exactly how I want it to show.
With this code it stores those numbers in long variable YYYY and as I type the numbers in that variable is displayed on PST (for debugging only). As I type the numbers in variable YYYY shows: 32000000, 32300000, 32303100 then 32303133. It stores the ascii hex equivalents of the numbers.

So here in lies the problem. I want the variable YYYY to contain the number as a whole, the hex equivalent of 2013 which is $07DD not just the individual numbers.

So how do I get there? Somehow I need to take those 4 individual numbers and convert them into one number and store the hex value of it.
    if tch == $01
      case idx
        0..3:
          YYYY.byte[idx] := key                     ' Year 4 bytes - 1 word
          repeat i from 0 to 3
            disp.Put_Char(byte[@YYYY][i])
          if idx == 3
            disp.Move_Cursor($0005, $0001) 
            disp.Put_String(@month)
          term.dec(idx)
          term.tx($20)
          term.hex(key, 2)
          term.tx($20)
          repeat i from 0 to 3
            term.hex(byte[@YYYY][i], 2)
            'term.str(byte[@YYYY][i])
          term.tx(13)    
        4..5:
          term.dec(idx)
          term.tx($20)
          term.hex(key, 2)
          term.tx(13) 
          disp.Move_Cursor($0005, $0001) 
          disp.Put_String(@month)
          MM_DD_YYYY.byte[idx] := key                     ' Month 2 bytes
          repeat i from 4 to 5
            disp.Put_Char(byte[@MM_DD_YYYY][i])
          if idx == 5
            disp.Move_Cursor($0006, $0001) 
            disp.Put_String(@date)   
        6..7:
          term.dec(idx)
          term.tx($20)
          term.hex(key, 2)
          term.tx(13)
          disp.Move_Cursor($0006, $0001) 
          disp.Put_String(@date)
          MM_DD_YYYY.byte[idx] := key                     ' Date 2 bytes
          repeat i from 6 to 7
            disp.Put_Char(byte[@MM_DD_YYYY][i])
          if idx == 7
            disp.Move_Cursor($0008, $0001)                          
            disp.Put_String(@day1)
            disp.Move_Cursor($0009, $0001)
            disp.Put_String(@day2)
            disp.Move_Cursor($000B, $0001)
            disp.Put_String(@day3) 
        8:
          term.dec(idx)
          term.tx($20)
          term.hex(key, 2)
          term.tx(13)
          'idx2 := idx - 7
          disp.Move_Cursor($0008, $0001)                         ' Day 1 byte 
          disp.Put_String(@day1)
          disp.Move_Cursor($0009, $0001)
          disp.Put_String(@day2)
          disp.Move_Cursor($000B, $0001)
          disp.Put_String(@day3) 
          DW_HH_MM_SS.byte[idx - 8] := key 
          disp.Put_Char(byte[@DW_HH_MM_SS][idx - 8])
          if idx == 8
            disp.Move_Cursor($000C, $0001) 
            disp.Put_String(@hour)  
        9..10:
          'idx2 := idx - 7 
          disp.Move_Cursor($000C, $0001) 
          disp.Put_String(@hour)
          DW_HH_MM_SS.byte[idx - 8] := key                   ' Hour 2 bytes
          repeat i2 from 1 to 2 
            disp.Put_Char(byte[@DW_HH_MM_SS][i2])
          if idx == 10
            disp.Move_Cursor($000D, $0001) 
            disp.Put_String(@minute)  
        11..12:
          'idx2 := idx - 7 
          disp.Move_Cursor($000D, $0001) 
          disp.Put_String(@minute)
          DW_HH_MM_SS.byte[idx - 8] := key                   ' Minutes 2 bytes
          repeat i2 from 3 to 4 
            disp.Put_Char(byte[@DW_HH_MM_SS][i2])
          DW_HH_MM_SS.byte[5] := $30                      ' Seconds 2 bytes
          DW_HH_MM_SS.byte[6] := $30              
      idx ++

Comments

  • SRLMSRLM Posts: 5,045
    edited 2013-02-19 12:04
    You need a decimal to ASCII routine. Basically, something like this would work (psuedocode, with a hint of C):
    int ASCII_to_Dec(char * string):
    	int result = 0
    	while(string != 0):
    		result = (result*10) + (*string - '0')
    		string++
    	return result
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-02-19 12:07
    You could simply set a variable to 0 before entering the date for example date_val := 0. In the case where you process the date Input you can do

    date_val := date_val*10 + Byte[@YYYY]-$30

    So, let's say you enter a 2, it's date_val := 0*10 + $32-$30 = 2
    next number: 0 => date_val := 2*10 + $30-$30 = 20
    next number: 1 => date_val := 20*10 + $31-$30 = 201
    next number: 3 => date_val := 201*10 + $33-$30 = 2013
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-02-19 12:12
    PST has a method DecIn. It pretty much does what you want. It requires a carriage return as the final character.

    I think there are also methods like this in the "Numbers" or "SimpleNumber" object.

    Edit: Sorry, I didn't read OP carefully enough. The methods I mentioned assume characters are stored as bytes.
  • Don MDon M Posts: 1,652
    edited 2013-02-19 12:15
    MagIO2- I was trying something similar to that earlier where I would try and "build up" the number but I couldn't get that to work. I'll look at your method.

    I can change my touch key code to return the numbers 0 - 9 instead of their hex equivalents if the would make anything easier.

    SRLM- I'm not well versed in C so I don't quite follow your code.
  • SRLMSRLM Posts: 5,045
    edited 2013-02-19 12:48
    Ok, here is a less C like version:
    int ASCII_to_Dec(byte array string):
    	int result = 0
    	for(int i = 0; string[i] != 0; i++)
    		result = (result*10) + (string[i] - '0')
    	return result
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-02-19 13:18
    What SRLM proposes is basically the same than the code I proposed. The difference is, that SRLM's function would have been called after all digits have been entered vs. doing the conversion on the fly. And SRLM did not give you SPIN-code.

    If the touch would return 0-9 instead of "0"-"9" you'd save the -$30 in the line of code I mentioned above. But on the other hand you'd need to do a +$30 before sending the number to the display. So, no real win!
  • Don MDon M Posts: 1,652
    edited 2013-02-19 13:50
    MagIO2 wrote: »
    What SRLM proposes is basically the same than the code I proposed. The difference is, that SRLM's function would have been called after all digits have been entered vs. doing the conversion on the fly. And SRLM did not give you SPIN-code.

    If the touch would return 0-9 instead of "0"-"9" you'd save the -$30 in the line of code I mentioned above. But on the other hand you'd need to do a +$30 before sending the number to the display. So, no real win!

    I got your code snippet to work. Thanks very much.

    Now I have another strange problem. See my new post.
  • Don MDon M Posts: 1,652
    edited 2013-02-19 17:47
    So I am trying to work through the rest of this code using MagIO2's suggestion but I am having a problem with the "date" and "month" portion of this code.

    If there is a simpler way to do this I'm all ears...
    VAR
    
      long  MM_DD_YYYY, YYYY, DD, MM, Date_MM, Date_DD
      long  key
    
    
    PUB
    
          case idx
            0..3:                                           ' Year 4 bytes - 1 word 
              YYYY.byte[idx] := key                         ' Store in temp year buffer for display                        
              repeat i from 0 to 3
                disp.Put_Char(byte[@YYYY][i])               ' Display year buffer as data is input
              MM_DD_YYYY := (MM_DD_YYYY*10) + (key-$30)     ' Build up bytes for main date buffer  
              if idx == 3                                   ' Que for next input string message
                disp.Move_Cursor($0005, $0001) 
                disp.Put_String(@date)
            4..5:                                           ' Date 2 bytes
              DD.byte[idx-4] := key                         ' Store in temp date buffer for display                          
              disp.Move_Cursor($0005, $0001)                ' Position cursor for string and date input
              disp.Put_String(@date)
              repeat i from 0 to 1                          ' Display date buffer as data is input
                disp.Put_Char(byte[@DD][i])
              byte[Date_DD][2] := (Date_DD * 10) + (key - $30)  ' Build up bytes for date buffer and position as same place as in main buffer   
              MM_DD_YYYY := MM_DD_YYYY | Date_DD            ' OR date buffer with main buffer to preserve data positions                
              if idx == 5                                   ' Que for next input string message
                disp.Move_Cursor($0006, $0001) 
                disp.Put_String(@month)
            6..7:                                           ' Month 2 bytes 
              MM.byte[idx-6] := key                         ' Store in temp month buffer for display                           
              disp.Move_Cursor($0006, $0001)                ' Position cursor for string and month input
              disp.Put_String(@month)
              repeat i from 0 to 1                          ' Display month buffer as data is input
                disp.Put_Char(byte[@MM][i])
              byte[@Date_MM][3] := (Date_DD * 10) + (key - $30)  ' Build up bytes for month buffer and position as same place as in main buffer
              MM_DD_YYYY := MM_DD_YYYY | Date_MM            ' OR month buffer with main buffer to preserve data positions
          idx ++
    
    DAT
    
    year    byte  "Enter year (2000-2099): ",0
    date    byte  "Enter date (01-31): ",0
    month   byte  "Enter month (01-12): ",0
    


    If I was to enter todays date- 2013 19 02 what I would expect the MM_DD_YYYY buffer to look like is 021307DD

    It would be broken down like this: 02 is byte[3] and is the month in hex. 13 is byte[2] and is the date in hex. 07DD is bytes [0] and [1] and is the year in hex.

    What I'm getting is this: 020007DD. For some reason this code won't work right for the "date" or "month" if there is a number greater than 0 in the tens column portion.

    As I mentioned earlier if there is an easier way to accomplish this I'd appreciate it.

    Thanks in advance.
  • SRLMSRLM Posts: 5,045
    edited 2013-02-19 17:58
    If you're going to use the snippet that MagIO2 posted, you need to do the math on each character in the string that you want to convert.
  • Don MDon M Posts: 1,652
    edited 2013-02-19 18:03
    SRLM wrote: »
    If you're going to use the snippet that MagIO2 posted, you need to do the math on each character in the string that you want to convert.

    I guess what I don't understand is why it works for the year portion and not the others...

    I thought I was doing the math for each segment as it goes through the repeat loop. But I must not be.
  • kuronekokuroneko Posts: 3,623
    edited 2013-02-19 18:15
    What's wrong with these two lines?
              byte[Date_DD][2] := (Date_DD * 10) + (key - $30)  ' Build up bytes for date buffer and position as same place as in main buffer   
              byte[@Date_MM][3] := (Date_DD * 10) + (key - $30)  ' Build up bytes for month buffer and position as same place as in main buffer
    
    This works for me:
    CON
      _clkmode = XTAL1|PLL16X
      _xinfreq = 5_000_000
    
    OBJ
      serial: "FullDuplexSerial"
      
    VAR
      long  MM_DD_YYYY
    
    PUB main : n | addr
    
      serial.start(31, 30, %0000, 115200)
      waitcnt(clkfreq*3 + cnt)
      serial.tx(0)
    
      addr := string("20131302")
      repeat strsize(addr)
        accumulate(n++, byte[addr++])
    
      serial.hex(MM_DD_YYYY, 8)
      serial.tx(13)
    
    [COLOR="blue"]PRI accumulate(idx, key)
    
      key -= "0"
    
      ifnot idx
        MM_DD_YYYY := key
      elseif idx < 4
        MM_DD_YYYY.word{0} := 10*MM_DD_YYYY.word{0} + key
      else
        MM_DD_YYYY.byte[idx/2] := 10*MM_DD_YYYY.byte[idx/2] + key
    [/COLOR]
    DAT
    
  • Don MDon M Posts: 1,652
    edited 2013-02-19 18:15
    Found a couple of typos but didn't fix...

    And I do initialize all the variables to 0 in case you were wondering.
    VAR
    
      long  MM_DD_YYYY, YYYY, DD, MM, Date_MM, Date_DD
      long  key
    
    
    PUB
    
          case idx
            0..3:                                           ' Year 4 bytes - 1 word 
              YYYY.byte[idx] := key                         ' Store in temp year buffer for display                        
              repeat i from 0 to 3
                disp.Put_Char(byte[@YYYY][i])               ' Display year buffer as data is input
              MM_DD_YYYY := (MM_DD_YYYY*10) + (key-$30)     ' Build up bytes for main date buffer  
              if idx == 3                                   ' Que for next input string message
                disp.Move_Cursor($0005, $0001) 
                disp.Put_String(@date)
            4..5:                                           ' Date 2 bytes
              DD.byte[idx-4] := key                         ' Store in temp date buffer for display                          
              disp.Move_Cursor($0005, $0001)                ' Position cursor for string and date input
              disp.Put_String(@date)
              repeat i from 0 to 1                          ' Display date buffer as data is input
                disp.Put_Char(byte[@DD][i])
              Date_DD.byte[2] := (Date_DD*10) + (key-$30)  ' Build up bytes for date buffer and position as same place as in main buffer   
              MM_DD_YYYY := MM_DD_YYYY | Date_DD            ' OR date buffer with main buffer to preserve data positions                
              if idx == 5                                   ' Que for next input string message
                disp.Move_Cursor($0006, $0001) 
                disp.Put_String(@month)
            6..7:                                           ' Month 2 bytes 
              MM.byte[idx-6] := key                         ' Store in temp month buffer for display                           
              disp.Move_Cursor($0006, $0001)                ' Position cursor for string and month input
              disp.Put_String(@month)
              repeat i from 0 to 1                          ' Display month buffer as data is input
                disp.Put_Char(byte[@MM][i])
              Date_MM.byte[3] := (Date_MM*10) + (key-$30) ' Build up bytes for month buffer and position as same place as in main buffer
              MM_DD_YYYY := MM_DD_YYYY | Date_MM            ' OR month buffer with main buffer to preserve data positions
          idx ++
    
    DAT
    
    year    byte  "Enter year (2000-2099): ",0
    date    byte  "Enter date (01-31): ",0
    month   byte  "Enter month (01-12): ",0
    
  • Don MDon M Posts: 1,652
    edited 2013-02-19 18:19
    kuroneko wrote: »
    What's wrong with these two lines?
              byte[Date_DD][2] := (Date_DD * 10) + (key - $30)  ' Build up bytes for date buffer and position as same place as in main buffer   
              byte[@Date_MM][3] := (Date_DD * 10) + (key - $30)  ' Build up bytes for month buffer and position as same place as in main buffer
    
    This works for me:
    CON
      _clkmode = XTAL1|PLL16X
      _xinfreq = 5_000_000
    
    OBJ
      serial: "FullDuplexSerial"
      
    VAR
      long  MM_DD_YYYY
    
    PUB main : n | addr
    
      serial.start(31, 30, %0000, 115200)
      waitcnt(clkfreq*3 + cnt)
      serial.tx(0)
    
      addr := string("20131302")
      repeat strsize(addr)
        accumulate(n++, byte[addr++])
    
      serial.hex(MM_DD_YYYY, 8)
      serial.tx(13)
    
    [COLOR="blue"]PRI accumulate(idx, key)
    
      key -= "0"
    
      ifnot idx
        MM_DD_YYYY := key
      elseif idx < 4
        MM_DD_YYYY.word{0} := 10*MM_DD_YYYY.word{0} + key
      else
        MM_DD_YYYY.byte[idx/2] := 10*MM_DD_YYYY.byte[idx/2] + key
    [/COLOR]
    DAT
    

    Ok now that is some pared down code! I don't understand it so I'll have to work with it a bit at a time and figure it out.
  • kuronekokuroneko Posts: 3,623
    edited 2013-02-19 18:25
    Don M wrote: »
    Date_DD.byte[2] := (Date_DD*10) + (key-$30)  ' Build up bytes for date buffer and position as same place as in main buffer   
              MM_DD_YYYY := MM_DD_YYYY | Date_DD            ' OR date buffer with main buffer to preserve data positions                
    
    You only want to modify Date_DD.byte[2] so that the final binary OR works. This means the RHS should be based on that as well, e.g.
    Date_DD.byte[2] := Date_DD[COLOR="#FF0000"].byte[2][/COLOR]*10 + (key-$30)
    
    Same for month handling ...
  • Don MDon M Posts: 1,652
    edited 2013-02-19 19:04
    kuroneko wrote: »
    You only want to modify Date_DD.byte[2] so that the final binary OR works. This means the RHS should be based on that as well, e.g.
    Date_DD.byte[2] := Date_DD[COLOR="#FF0000"].byte[2][/COLOR]*10 + (key-$30)
    
    Same for month handling ...

    That fixed it! Thanks a million!

    I still want to understand your code better and see if I can incorporate that into this. It has the appearance of being much simpler. Would you mind commenting your code for me? I'm not looking for you to incorporate it into my code but a better understanding of yours so that I may attempt at putting it to use myself.

    Thanks again!
  • kuronekokuroneko Posts: 3,623
    edited 2013-02-19 19:17
    Don M wrote: »
    Would you mind commenting your code for me? I'm not looking for you to incorporate it into my code but a better understanding of yours so that I may attempt at putting it to use myself.
    HTH
    PUB main : n | addr
    
      serial.start(31, 30, %0000, 115200)                   ' |
      waitcnt(clkfreq*3 + cnt)                              ' |
      serial.tx(0)                                          ' debug setup
    
      addr := string("20131302")                            ' emulate 8 key presses
      repeat strsize(addr)                                  ' send 8 keys
        accumulate(n++, byte[addr++])                       ' idx: 0..7, key: byte[addr][0]..byte[addr][7]
    
      serial.hex(MM_DD_YYYY, 8)                             ' |
      serial.tx(13)                                         ' print collected date
    
    PRI accumulate(idx, key)
    
      key -= "0"                                            ' "0".."9" >> 0..9 (ASCII to numeric)
    
    [COLOR="grey"]' first index is 0 which is conveniently used to initialise
    ' the date variable (not just the year) with the first key[/COLOR]
      ifnot idx
        MM_DD_YYYY := key
    [COLOR="grey"]' keys 1..3 complete year conversion, year is stored in the low-word
    ' so we limit all calculations to it, limit is not strictly required[/COLOR]
      elseif idx < 4
        MM_DD_YYYY.word{0} := 10*MM_DD_YYYY.word{0} + key
    [COLOR="grey"]' keys 4..7 are for date and month, dividing by 2 results in 2 and 3
    ' respectively which is used as a byte index, calculation as usual[/COLOR]
      else
        MM_DD_YYYY.byte[idx/2] := 10*MM_DD_YYYY.byte[idx/2] + key
    
    
  • Don MDon M Posts: 1,652
    edited 2013-02-19 20:00
    Yes. Thank you.
Sign In or Register to comment.