Shop OBEX P1 Docs P2 Docs Learn Events
Quick Question about addresses in memeory in spin — Parallax Forums

Quick Question about addresses in memeory in spin

I am using the propeller RTC emulator program from the OBEX. it has a demo that I can program the time and then see it display in the terminal window.
It has a variable of byte TimeStamp[11]
and then uses
ser.str(@TimeStamp)
to display the time on the screen and it shows 09:14:04pm (11 characters)

I want to only display the hours which is TimeStamp[1] and TimeStamp[2]

when I tell it to
ser.str(@TimeStamp[1] thinking I was going to get just the 9, but I get 9:14:04pm
and if I use
ser.str(@TimeStamp[2] I get :14:04pm


What I really want to do is an action every hour. what I was thinking to do was to initiate my tracking variable with the current hour. add 1 to it and store it in an other variable and constantly compare the two. when they match, do my action and then add one again.

Please tell me there is an easier way.

Comments

  • Cluso99Cluso99 Posts: 18,069
    When you use a string type, you are referring to a group of characters terminated with a $0.

    You can make another variable, say
    hh byte[2]
    Then
    hh[1] := TimeStamp[1]
    hh[2] := TimeStamp[2]

    You can do the same to break apart the rest.

    Alternately you could replace the ":" with "nul" ($0)
    hh[3] := 0
    Now
    Ser.str(@TimeStamp) will print the hours because the string is terminated where the : used to be.
  • ChrisGaddChrisGadd Posts: 310
    edited 2016-08-31 11:28
    Arrays are zero-indexed, meaning that for the string '09:14:04pm' Timestamp[0] contains the tens of hours and Timestamp[1] contains the single hours, Timestamp[2] contains the first colon.

    If you just want to perform an action once an hour, and don't care what the hour is, I'd make a copy Timestamp[1] and then compare the copy to Timestamp[1]. You know the hour changed as soon as they differ, then just copy the new byte and perform your action. This saves you from having to increment the hour and perform range checks.

    Chris
  • JonnyMacJonnyMac Posts: 9,104
    edited 2016-08-31 18:58
    The tx() method will let you print one character at a time -- and you can do it without creating any new variables
    dat
    
      TimeStamp     byte    "12:34:56", 0                                                             
                                                                     
                                                                     
    pub main | idx                                                        
                                                                     
      setup                                                          
                                                                     
      term.rxflush
      term.rx                                                        
      term.tx(term#CLS)                                              
    
      term.str(@TimeStamp)
      term.tx(13)
    
      repeat idx from 0 to 7
        term.tx(byte[@TimeStamp][idx])
        term.tx(13)
    

    I suggest you add a method to your program that can print a portion of a string. For example:
    pub sub_str(p_str, first, len) | c
    
      p_str += first
    
      repeat len
        c := byte[p_str++]
        if (c > 0)
          term.tx(c)
        else
          quit
    

    This method takes the base address of a string, the first character to print, and the number of characters to print. To print hours:
    sub_str(@TimeStamp, 0, 2)
    

    The same method will let you print the minutes and seconds fields as easily.
  • ChrisGadd wrote: »
    Arrays are zero-indexed, meaning that for the string '09:14:04pm' Timestamp[0] contains the tens of hours and Timestamp[1] contains the single hours, Timestamp[2] contains the first colon.

    If you just want to perform an action once an hour, and don't care what the hour is, I'd make a copy Timestamp[1] and then compare the copy to Timestamp[1]. You know the hour changed as soon as they differ, then just copy the new byte and perform your action. This saves you from having to increment the hour and perform range checks.

    Chris
    clearly i am missing something here
    this is the code
    * Author: Beau Schwabe *
    * Copyright (c) 2009 Parallax *
    * See end of file for terms of use. *
    ************************************************
    }}

    CON
    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000

    OBJ
    Clock : "PropellerRTC_Emulator"
    Ser : "FullDuplexSerial"
    VAR
    long TimeString
    byte SS,MM,HH,AP,DD,MO,YY,LY
    byte DateStamp[11], TimeStamp[11]
    byte hour

    PUB PropellerRTC_EmulatorDemo

    Ser.start(31, 30, 0, 2400) '' Initialize serial communication to the PC

    Clock.Start(@TimeString) '' Initiate Prop Clock

    Clock.Suspend '' Suspend Clock while being set

    Clock.SetYear(16) '' 00 - 31 ... Valid from 2000 to 2031
    Clock.SetMonth(08) '' 01 - 12 ... Month
    Clock.SetDate(30) '' 01 - 31 ... Date

    Clock.SetHour(09) '' 01 - 12 ... Hour
    Clock.SetMin(44) '' 00 - 59 ... Minute
    Clock.SetSec(00) '' 00 - 59 ... Second

    Clock.SetAMPM(1) '' 0 = AM ; 1 = PM

    Clock.Restart '' Start Clock after being set
    Clock.ParseDateStamp(@DateStamp)
    hour := (@datestamp[2])

    repeat
    Clock.ParseDateStamp(@DateStamp)
    Clock.ParseTimeStamp(@TimeStamp)

    ser.tx(1) '' Send the HOME code to the DEBUG terminal
    ser.str(@DateStamp) '' Display Date to the DEBUG terminal
    ser.str(string(" "))
    ser.str(@TimeStamp) '' Display Time to the DEBUG terminal

    if i add
    ser.str (@timeStamp[0])
    i dont just get the tens of the hour. i get the entire string just like if I write ser.str(@timeStamp)


  • Duane DegnDuane Degn Posts: 10,588
    edited 2016-09-05 03:59
    Here's the code inside code tags:
    * Author: Beau Schwabe                         *
    * Copyright (c) 2009 Parallax                  *
    * See end of file for terms of use.            *
    ************************************************
    }}
    
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    OBJ
      Clock         : "PropellerRTC_Emulator"
      Ser           : "FullDuplexSerial"
    VAR
      long  TimeString
      byte  SS,MM,HH,AP,DD,MO,YY,LY
      byte  DateStamp[11], TimeStamp[11]
      byte  hour
    
    PUB PropellerRTC_EmulatorDemo
    
        Ser.start(31, 30, 0, 2400)  '' Initialize serial communication to the PC
      
        Clock.Start(@TimeString)    '' Initiate Prop Clock 
    
        Clock.Suspend               '' Suspend Clock while being set
    
        Clock.SetYear(16)           '' 00 - 31 ... Valid from 2000 to 2031
        Clock.SetMonth(08)          '' 01 - 12 ... Month
        Clock.SetDate(30)           '' 01 - 31 ... Date
        
        Clock.SetHour(09)           '' 01 - 12 ... Hour        
        Clock.SetMin(44)            '' 00 - 59 ... Minute    
        Clock.SetSec(00)            '' 00 - 59 ... Second
    
        Clock.SetAMPM(1)            '' 0 = AM ; 1 = PM
    
        Clock.Restart               '' Start Clock after being set    
        Clock.ParseDateStamp(@DateStamp)
        hour := (@datestamp[2])    
        
        repeat
          Clock.ParseDateStamp(@DateStamp)
          Clock.ParseTimeStamp(@TimeStamp)
    
          ser.tx(1)                 '' Send the HOME code to the DEBUG terminal      
          ser.str(@DateStamp)       '' Display Date to the DEBUG terminal 
          ser.str(string("  "))
          ser.str(@TimeStamp)       '' Display Time to the DEBUG terminal
    
    

    The time is stored in the "timeStamp" array as ASCII characters. To access the individual characters in the array use the method provided by JonnyMac.

    I imagine the RTC object also includes methods which would allow you to access the various components of the current time without having these values converted to ASCII characters.


  • Try adding this to the end of the repeated code:
      ser.str(string(13, "Hour = "))
      ser.dec(HH)
    

    I'm guessing it will display the hour.

    I think the other time elements are available as variables listed here:
    byte SS,MM,HH,AP,DD,MO,YY,LY
    

  • this is where it gets put into the string
    PUB ParseTimeStamp(DataAddress)
        DateTimeStamp[0] := $30 + HH/10                    ''<-Hour
        DateTimeStamp[1] := $30 + HH-(HH/10)*10             '<-Hour
        DateTimeStamp[2] := ":"    
        DateTimeStamp[3] := $30 + MM/10                    ''<-Minute
        DateTimeStamp[4] := $30 + MM-(MM/10)*10             '<-Minute
        DateTimeStamp[5] := ":"    
        DateTimeStamp[6] := $30 + SS/10                    ''<-Second
        DateTimeStamp[7] := $30 + SS-(SS/10)*10             '<-Second
        if AP < 1
           DateTimeStamp[8] := "a"                         ''<-Set am
        else
           DateTimeStamp[8] := "p"                         ''<-Set pm
        DateTimeStamp[9] := "m"   
        DateTimeStamp[10] := 0      ' String Terminator ALWAYS Zero
        bytemove(DataAddress,@DateTimeStamp,11)
    
  • It looks like the time is available both as a string of ASCII characters and as individual values.

    To access the individual values see my earlier post.
Sign In or Register to comment.