Shop OBEX P1 Docs P2 Docs Learn Events
Print to screen — Parallax Forums

Print to screen

JOSHTJOSHT Posts: 8
edited 2012-02-22 23:00 in Propeller 1
Hello. I'm Pretty new to the propeller chip and am learning to print to a terminal window. Right now I'm using the PC_Interface.spin file that came in the demo.
I'm trying to find some resources on how the print commands work. Right now i can print to the screen but am having a hard time with keeping the words and number in the same spot on the screen. They scroll up and I eventually lose the old text.
Does anyone know of any good resources that may help with this, and eventually help with using a VGA or TV monitor.
Thanks

Comments

  • Cluso99Cluso99 Posts: 18,069
    edited 2012-02-18 16:28
    Firstly, welcome to the fabulaous prop forum.

    I presume you are using PST (Parallax Serial Terminal) on the pc end. This can be invoked by F12 in PropTool.

    You can clear the screen with a fdx.tx(0) using the FullDuplexSerial object. There is also a PST object that may have more functions.

    If you want a simple 1pin and 1 resistor TV interface where you can control you position on screen, see my Debug 1pin TV and Keyboard objects.
  • JOSHTJOSHT Posts: 8
    edited 2012-02-18 17:15
    Thanks for your help. Actually I'm using the Prop Terminal 0.4. It uses an application that is an emulated terminal window on the PC in conjunction with an .spin object file. I hope to soon attach a monitor directly to the board.
    I tried the command you gave me it doesn't work I assume it is because it is for the terminal built into the Prop Tool.
    Thanks
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-02-18 19:34
    I'm not sure about the propeller terminal, but when you get to a real display like a TV or VGA there are some simple commands to move the cursor to a certain row or column. Eg in this little code fragment, send ascii $01 to set the x position or $0B to set the y position
    PUB out(c) | i, k
    
    '' Output a character
    ''
    ''     $08 = backspace
    ''     $09 = tab (8 spaces per)
    ''     $01 = set X position (X follows)
    ''     $0B = set Y position (Y follows)
    ''     $0C = set color (color follows)
    ''     $0A = line feed
    ''     $0D = carriage return (col = 0)
    ''  others = printable characters
    
      case flag
        $00: case c
               $08: if col
                      col--
               $09: repeat
                      print(" ")
                    while col & 7
               $01: flag := c
                 return
               $0B: flag := c
                 return
               $0C: flag := c
                 return
               $0A: newline ' linefeed/new line     
               $0D: col := 0 ' carriage return
               other: print(c)
        $0A: col := c // cols
        $0B: row := c // rows
        $0C: color := c & 7
      flag := 0
    
  • SRLMSRLM Posts: 5,045
    edited 2012-02-18 22:50
    Note that if you want to keep your objects "standard", then there's not too much you can do for moving the cursor backwards. A serial terminal program (like Cutecom or picocom) may not implement the different movement commands. Usually what I do is either do a line by line running debug and just ignore the offscreen stuff, or output all the data in a nicely formed "page" of maybe 10-30 lines that has all the information. Then each time you output a new page, the position of the constant characters (labels, column headers, etc.) stays the same, but the data changes because a serial terminal will place all new data at the bottom.
  • StefanL38StefanL38 Posts: 2,292
    edited 2012-02-19 01:20
    Hello Josh,

    welcome to the propeller-forum.

    To give you a better support, I would like to ask some questions to know better what you are doing:

    What's your programming experience you are coming from?
    the words print to screen remind me of the keyboard-button "PrtScr". But from this I can not conclude what your programming backround is.

    What do you want to pint to screen some debug-info (which could run through vanaishing) or do you code a userinterface?

    What kind of screen are printing on? Parallax Serial Terminal, TV, VGA-monitor connected directly to the propeller

    PC_Interface reminds me of "PropTerminal" a software for PC that emulates the TV-object through a serial connection on the PC.

    Please post some more specific information and attach your code

    keep the questions coming
    best regards
    Stefan
  • JOSHTJOSHT Posts: 8
    edited 2012-02-19 13:55
    First I just want to say thank you all for you help.

    Well I have taken a C programming class in college and a class where we used PBasic. I have also used an Arduino a little bit, but not much.

    I guess I was looking for commands similar to those found in C. Like the printf command and implementation of /t and such for returning and tabbing.
    Right now I have been using the Prop Terminal on the PC. i would like to eventually have an external monitor; VGA or TV, haven't decided yet.
    I have been using it to debug. But I would like to print some time and date information on the screen and have it stay in one place. Then under it I would like
    to place some variable information that changes as the program executes so the step of the program can be viewed. Eventually I would like to scan some
    inputted data from the interface as well. Maybe have some questions that are answered via a key pad or keyboard.

    Does it take a programing object to use those ascii commands like the $08 for backspace? Or are they built in to the spin language? If it is easier I will
    switch to a VGA or TV monitor now since that is where I am headed anyway.
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-02-19 14:12
    The Parallax Serial Terminal allows positioning and also supports backspace and other specialities. When PST is running click on prefs... -button and switch to Functions - tab. There you find a list of functions and can switch them on and off.

    On propeller side you'd simply call
    serial.tx( 0 ) ' for clearing the terminal screen
    serial.tx( 1 ) ' for set cursor to home position = 0,0
    serial.tx( 2 ) followed by serial.tx( x ) and serial.tx( y ) for setting cursor to any position you want

    You can easily create some functions in SPIN which allow to output any value into a mask.
  • AribaAriba Posts: 2,690
    edited 2012-02-19 19:49
    Hi JOSHT

    I'm the author of the PropTerminal and the Spin interface objects.
    There are several objects for the PropTerminal:
    - PC_Text
    - PC_Keyboard
    - PC_Mouse
    - PC_Interface
    The first 3 are direct replacements for the Parallax object: TV_Text.spin/VGA_Text.spin, Keyboard.spin and Mouse.spin.
    The PC_Interface.spin is a combination of all with some added graphic routines and needs only one cog.

    If you make a code with PC_Text for example, then you can later just switch to a TV monitor by replacing the PC_Text object with the TV_Text (maybe you have also to change the basepin parameter of the start call).
    The same for the Keyboard and Mouse.

    If you use PC_:Interface you get a lot of useful methodes. To place the cursor at a X,Y position you can use the locate(x,y) methode, to change the color use setcol(color). It may help you to look at the source of this routines to see how the output of the control characters is done for that methodes.
    For outputting data and strings like printf, you can use the methodes dec, hex, bin, str, and out.
    something like:
    OBJ
      pc : "pc_interface"
    
    PUB
     ...
      pc.out(0)  'control character for clear screen
      pc.str(string("X position = "))
      pc.dec(x)
      pc.str(string("as hex number: "))
      pc.hex(x,8)
     ...
    
    There are some demos in the PropTerminal ZIP file for that.

    Andy
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-02-19 23:19
    @JOSHT: Thanks for asking this question?
    I wasn't aware that there exists a program like PropTerminal so far and I asked so many times whether it's possible to have a terminal software which uses the propeller font.

    @Ariba: Thanks for the PropTerminal ... have to try it out this evening. (Even if I started my own terminal program a few days ago - but besides using the parallax font (resizable ;o) there are some other reasons for developing that)
  • JOSHTJOSHT Posts: 8
    edited 2012-02-20 15:28
    Thanks Dr_Acula, this is actaully part of the code in the pc_iterface.spin file. Took me minute to figure out how to use it but i have it working pretty good now.

    Dr_Acula wrote: »
    I'm not sure about the propeller terminal, but when you get to a real display like a TV or VGA there are some simple commands to move the cursor to a certain row or column. Eg in this little code fragment, send ascii $01 to set the x position or $0B to set the y position
    PUB out(c) | i, k
    
    '' Output a character
    ''
    ''     $08 = backspace
    ''     $09 = tab (8 spaces per)
    ''     $01 = set X position (X follows)
    ''     $0B = set Y position (Y follows)
    ''     $0C = set color (color follows)
    ''     $0A = line feed
    ''     $0D = carriage return (col = 0)
    ''  others = printable characters
    
      case flag
        $00: case c
               $08: if col
                      col--
               $09: repeat
                      print(" ")
                    while col & 7
               $01: flag := c
                 return
               $0B: flag := c
                 return
               $0C: flag := c
                 return
               $0A: newline ' linefeed/new line     
               $0D: col := 0 ' carriage return
               other: print(c)
        $0A: col := c // cols
        $0B: row := c // rows
        $0C: color := c & 7
      flag := 0
    




    Here is some code I made if anyone is interested. Was trying to get a feel for printing and using multiple cogs. So I made a mock program that counts up using Data and tells if the number pulled is between 1..5 or 6..10.

    CON
      _CLKMODE        =XTAL1 + PLL2X
      _XINFREQ        = 5_000_000
    
      #0, WHITE,CYAN,RED,PINK,BLUE,GREEN,YELLOW,GRAY
      WAITPERIOD2     =5_000_000
    
    VAR
      LONG  stack2[50], A, B, X
    
    OBJ
      term: "pc_interface"
      
    PUB Go
     
      cognew(Terminal, @stack2)
      term.start(31,30)
    
      repeat  1 
        term.setcol(GREEN)
        term.str(string("X:   "))
        
      REPEAT 2
        WAIT
      REPEAT 10
        Getdata
        math
        REPEAT 2
          WAIT
        B++
      
    PUB Getdata | Day1
      A := Day[B]    
    
    PUB math
      Case A
        1..5: X := 1
        6..10: X := 0
      
    PUB WAIT
        WAITCNT(WAITPERIOD2*2 + CNT)
    
    PUB Terminal
      term.start(31,30)
    
      REPEAT 11   
        IF  X == 1
          term.str(string(" ",$08,$08,$08,$08,$08,$08))
          term.setcol(RED)
          term.str(string("YES "))
          term.dec(A)
          REPEAT 2
            WAIT
        ELSE
          term.str(string(" ",$08,$08,$08,$08,$08,$08))
          term.setcol(RED)
          term.str(string("NO  "))
          term.dec(A)
          REPEAT 2
            WAIT
         
    DAT
    Day       Long 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
        
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-02-20 23:01
    What exactly is a repeat 1 good for?

    I did not have a look into PC_interface.spin yet, but most times you should not start the same instance of an object in different COGs when using the same PINs. Well ... this field of knowledge is very complex. In the end it depends on how the object has been implemented. Does it start another COG or not? If not, is it setting DIRA in the start method never touching it again?

    From what I remember from the readings yesterday the PC_interface is starting a COG for the communication with the PC. In this case the start functions usually stop a previously started COG. If you have a driver that runs a COG on it's own, most times there is no problem to share the driver. So, even if it is started in your Go function it can also be used in Terminal without starting it again. That's because the PINs are driven by the PC_Interface-COG and the communication to the PC_I-COG is done via a HUB-RAM buffer. You only have to make sure that you don't call term.xxxx-functions from 2 different COGs at the same time.

    If you refere to the clockfrequency there is no need to define another constant. You could use clkfreq directly. This is also better in case you want to use the same code in another setup where you don't have a 5MHz crystal.
    WAITCNT(clkfreq*2 + CNT)

    *2 is doing a multiplication which is pretty slow. Shift operations are faster, so you could use clkfreq<<1 instead .... this way you can easily and fast multiply by 2, 4, 8, 16 ......

    I think it would also work to say
    WAITCNT( constant( clkfreq*2 ) + CNT )
    which will move the calculation of the 2s offset from runtime to compile-time. Ok ... save time in execution of a wait instruction might not make that much sense, but you also save power and HUB-RAM in this case.

    Your backspace implementation might work well for one number, but what happens if you want to show more content? I think it would be better to work with positioning and overwrite.

    Getdata works in the way you implemented it, but I think you should not get used to using global variables to much. In Go you count B up and in Getdata you use it. If you do this to often you get code wich will be hard to maintain. Use parameters instead, this makes the function more independend.

    What is Day1 good for?
  • JOSHTJOSHT Posts: 8
    edited 2012-02-22 18:54
    MagIO2 wrote: »
    What exactly is a repeat 1 good for?

    Well i forgot to remove that portion. I adapted code from something else to this so I could learn to use the terminal before I implemented it in the other program.
    MagIO2 wrote: »
    I did not have a look into PC_interface.spin yet, but most times you should not start the same instance of an object in different COGs when using the same PINs. Well ... this field of knowledge is very complex. In the end it depends on how the object has been implemented. Does it start another COG or not? If not, is it setting DIRA in the start method never touching it again?

    From what I remember from the readings yesterday the PC_interface is starting a COG for the communication with the PC. In this case the start functions usually stop a previously started COG. If you have a driver that runs a COG on it's own, most times there is no problem to share the driver. So, even if it is started in your Go function it can also be used in Terminal without starting it again. That's because the PINs are driven by the PC_Interface-COG and the communication to the PC_I-COG is done via a HUB-RAM buffer. You only have to make sure that you don't call term.xxxx-functions from 2 different COGs at the same time.

    I didn't realize that the term.start(31,30) was stating the pins until you said something. And I suppose that I don't need a second cog. i didn't know that it would use the cog in the object file to run the terminal.
    MagIO2 wrote: »
    If you refere to the clockfrequency there is no need to define another constant. You could use clkfreq directly. This is also better in case you want to use the same code in another setup where you don't have a 5MHz crystal.
    WAITCNT(clkfreq*2 + CNT)

    *2 is doing a multiplication which is pretty slow. Shift operations are faster, so you could use clkfreq<<1 instead .... this way you can easily and fast multiply by 2, 4, 8, 16 ......

    I think it would also work to say
    WAITCNT( constant( clkfreq*2 ) + CNT )
    which will move the calculation of the 2s offset from runtime to compile-time. Ok ... save time in execution of a wait instruction might not make that much sense, but you also save power and HUB-RAM in this case.

    So I can just put clkfreq<<1 instead of WAITCNT(clkfreq*2 + CNT) or should I put WAITCNT(clkfreq<<1 + CNT)?
    MagIO2 wrote: »
    Your backspace implementation might work well for one number, but what happens if you want to show more content? I think it would be better to work with positioning and overwrite.

    I have been wanting to print in specific locations. I have yet to figure out how though. I eventually want to rewrite certain numbers but have other things on the screen stay the same.
    MagIO2 wrote: »
    Getdata works in the way you implemented it, but I think you should not get used to using global variables to much. In Go you count B up and in Getdata you use it. If you do this to often you get code wich will be hard to maintain. Use parameters instead, this makes the function more independend.

    What do you mean use parameters? Are talking about using flags or something?
    MagIO2 wrote: »
    What is Day1 good for?

    The program wouldn't work unless I use a name that hadn't been used so that is what i chose. I don't understand why it made me do that.

    Thanks a bunch for all of you help.
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-02-22 23:00
    About term.start(31,30):
    As I said: "I did not have a look into PC_interface.spin yet". So, what I said about this was more a general statement which hopefully makes you think whenever you use a .start again. I think PC_interface.spin is starting a PASM driver which runs the pins. In your case it means term starts a COG with your first term.start. With the next term.start it stops the COG and starts it again. But you are right ... the SPIN portion of the driver always runs in the COG in which the term.xxxx -functions are called. And this is a problem when you call the functions at the same time, as the buffer for communicating with the PASM COG might be in an inconsistent state when the PASM reads it. So it is safer to just use term.xxx-functions from one COG only.

    about clkfreq<<1:
    The << only replaces the multiplication, so you have to use WAITCNT(clkfreq<<1 + CNT) here. Another option would be to define constants and use these. This makes code more readable and avoids calculation on runtime.

    about rewrite numbers:
    I'd implement a function like printDecAt which needs 4 parameters: x position, y position, number to print, number of digits to print. Whenever you have to print a number it will position the terminals cursor at the right place and completely overwrites the number that has been printed before. Have a look at post #9, Ariba describes how to set position there.

    about parameters:
    Getting used to work with parameters is a veriy basic skill in programming and very important. Parameters really make functions independend and usefull. You wrote:
      ....
      REPEAT 10
        Getdata
        math
        REPEAT 2
          WAIT
        B++
      
    PUB Getdata | Day1
      A := Day[B]    
    

    I'd suggest to do it like this:
      ....
      REPEAT 10
        A := Getdata(B)
        X := math( A )
        REPEAT 2
          WAIT
        B++
      
    PUB Getdata(whichDay) : returnDay
      returnDay := Day[whichDay]
    
    PUB math( input ) : output
       Case input
          1..5: output := 1
          6..10: output := 0
    

    You see the difference? The caller decides which data should be used and where the result goes. This makes functions more usable.

    But to be really honest ... I'd not use a function in Getdata case at all because it's a function which only contains one instruction. This only adds runtime on the cost of additional memory usage without any benefit.

    about Day1:
    Of course it does not allow names which already have been used, but what you do there is create a local variable which is never used. Solution is to simply remove the "| Day1".


    You're welcome!
Sign In or Register to comment.