Shop OBEX P1 Docs P2 Docs Learn Events
SPIN CODE EXAMPLES FOR THE BEGINNER (Public Version) - Page 2 — Parallax Forums

SPIN CODE EXAMPLES FOR THE BEGINNER (Public Version)

245678

Comments

  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-07 15:35
    IMHO, if the code posting keeps up, we'll be very 'primed' for the release of the chip and the IDE.
    Seeing the code, with comments, and some followup comments really helps to 'visulize' various elements of the language, it's features and it's capabilities.
    For example, after seeing Beau's 'Shaker' program, I was inspired to attempt the same with the BS2P. I'm still working on it.
    While most of the issues being brought up here are only for SPIN, I'm also getting a feel for how others program.
    This in turn is causing me to change slightly how I code; for the better.
    Some one once said, "Think out side the box," and sometimes thats real hard to achive, but at looking how different programmers approch various tasks here
    gives good example on that.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-07 16:20
    Hi Kaos,

    Years ago when I started consulting, I often had to throw out ALL the code from the programmers who preceded me. Fortunately, structured design with its emphasis on functional cohesion and loose coupling greatly improved the way programmers code. Structured design is still very important in Object Oriented Programming. See a Google search on: STRUCTURED DESIGN COHESION COUPLING.

    Thanks for your comments,

    Dave

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    PLEASE LET·ME KNOW IF YOU FIND THE VERSION WITH LESS DOCUMENTATION
    HELPFUL AND·I WILL CONTINUE TO POST TWO VERSIONS FOR EACH EXAMPLE.






    ··
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-07 19:18
    Ok, I have an idea I'de like clarified.

    If you run an object in free cog (see the debugger thread )...
    And a routine in that cog is marked PUB
    THerefor, from a different cog, I can call that routine?

    A vastly overstated example would be:
    A Cog that runs a main program, while other cogs can run 'support objects / code' that may have public functions / subs that can be called from the main cog.
    Still other cogs may be running totaly different code privatly within their own "space".

    Again, i refer to the debugger thread as the source of this idea / conception

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Martin HebelMartin Hebel Posts: 1,239
    edited 2006-03-07 19:43
    Kaos Kidd said...
    Ok, I have an idea I'de like clarified.

    If you run an object in free cog (see the debugger thread )...
    And a routine in that cog is marked PUB
    THerefor, from a different cog, I can call that routine?



    If you are talking Spin, all functions, routines, code, variables·reside in the shared 32K RAM.· The only thing in the cog is the Spin interpreter which accesses the 32K RAM to fetch the next byte code.

    So when you say run an object in a cog, it not an appropriate description.

    What PUB does, is for libraries makes functions public.

    Lets say I have a program called "Blinkme.Spin", with a function of
    PUB eye
       outa[noparse][[/noparse]1]:=1
       waitcnt(cnt+500000)
       outa[noparse][[/noparse]1]:=0
       Return
    
    



    From another program I can reference the above program as an object, and call that PUBlic function:
    OBJ
       Blinky: "Blinkme"
     
     PUB
       Blinky.eye
    
    


    Now, since the blink code is in shared RAM, we could have 8 different cogs all accessing the same·function without needing 8 copies of the function.
    ·
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-07 19:49
    Martin:
    Thanks. I've got a big smile on my face; the lights are on, I think, and getting brighter by the second!
    Oooh, the fun We shall have, oh little propeller chip and I.... Ohhhy what fun...

    [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2006-03-07 21:10
    This is·something I've been playing with for the last couple days -- original program by Beau with very small updates by me (geez, I hope he doesn't mind...).· This is very clever on Beau's part; the rctime() method is public an can be called manually if desired.· If a cog is available, you can use the start() method and then rctime gets its own cog and just runs all the time, so·any time you access your target variable it has a fresh value in it and you didn't have to worry about dreaded interrupts.

    '' *******************************
    '' *  RCTime                     *
    '' *    (c) 2006 Parallax, Inc.  *
    '' *******************************
    ''
    '' Used to read an RC circuit.  When start() method is used, the rctime()
    '' method is installed in its own cog and runs continuously until the
    '' stop() method is called.
    ''
    '' If no cog is available the rctime() method may be called as needed.
                                                     
    
    VAR
    
    
      long  cogon, cog
    
    
      long  rcstack[noparse][[/noparse]16]
      long  rctemp
      long  mode
       
      
    OBJ
    
     
      time : "Timing"
      
      
    PUB start(pin, state, rcvalueaddress) : okay
    
    
    '' Start background RCTIME driver - starts a cog
    '' -- returns false if no cog available
    
    
      stop
      okay := cogon := (cog := cognew(rctime(pin, state, rcvalueaddress), @rcstack)) > 0
      mode := 1
      
    PUB stop
    
    
    '' Stop rctime - frees a cog
    
    
      if cogon~
        cogstop(cog)
        
        
    PUB rctime(pin, state, rcvalueaddress)
    
    
    '' Read RC circuit and move result to rcvalueaddress
    '' -- if mode 1, will run continuously in own cog
    '' -- if mode 0, will terminate and may be called again manually
    
    
      repeat
        outa[noparse][[/noparse]pin] := state                                  ' set pin to state
        dira[noparse][[/noparse]pin] := 1                                      ' make pin an ouput
        time.pause1ms(1)                                    ' allow cap to (dis)charge
        dira[noparse][[/noparse]pin] := 0                                      ' make pin an input
        rctemp := cnt                                       ' get current counter
        waitpeq(1-state,|< pin, 0)                          ' wait for state change on pin
        rctemp := || (cnt - rctemp)                         ' calculate duration
        rctemp := rctemp - 1600                             ' adjust for instructions
        rctemp := rctemp >> 4                               ' scale value (divide by 16)
        long [noparse][[/noparse]rcvalueaddress] := rctemp                     ' move result to target
               
        if mode == 0                                        ' quit if called manually
          quit
    


    Here's a bit of a demo I'm playing with that uses RCTime:

    CON
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
     
      CR       = 13
      FF       = 12
      LF       = 10
    
    
      
    OBJ
    
      debug : "SimpleDebug" 
      rc    : "RCTime"
      delay : "Timing"   
      
    
    PUB start | potVal, idx
     
      if rc.start(9, 1, @potVal)                            ' start bkg RCTIME
        if debug.start(57600)                               ' start terminal
          repeat
            debug.putc(FF)                                  ' clear screen
            debug.str(@Title1)
            debug.dec(potVal)                               ' print pot value
            debug.str(@CrLf)
            debug.str(@Title2)
            idx := potVal / 403                             ' calculate index
            debug.dec(idx)                                  ' print it
            delay.pause1ms(250)
        else
          rc.stop                                           ' stop rc if no terminal cog    
       
    
    DAT
    
      Title1  byte  "The POT setting is: ", 0
      Title2  byte  "LED index is: ", 0
      CrLf    byte  CR, LF, 0
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax

    Post Edited (Jon Williams (Parallax)) : 3/7/2006 9:15:10 PM GMT
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2006-03-08 05:08
    Jon,

    "...original program by Beau with very small updates by me (geez, I hope he doesn't mind...)" - No sweat.

    If people are looking for comparisons, I designed this object to look and feel like the RCTIME people are
    currently used to. This object is written in pure Spin code, which at 80MHz gives you about a 200nS resolution
    compared to a 750nS you get with a BS2p or BS2px. The Maximum pulse width is about 53mS. Written in
    pure assembly, results could be much greater.

    Aside from normal mode operation I will call foreground, with the multi processing capabilities of the Propeller,
    you can launch the RCTIME object into a background mode using a separate COG. The benefit of running RCTIME
    in the background is that you can read the result at anytime. With foreground mode, the wait/pause/delay time
    inherent with RCTIME proportional to the result completely disappears when the command is used in background
    mode.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2006-03-08 05:33
    I think the code is quite clever, Beau, and Ken and I will be showing it to our guests this week.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2006-03-08 07:41
    Beau -

    I basically understand your comment about "normal mode operation (which) I will call foreground, with the multi processing capabilities of the Propeller, you can launch the RCTIME object into a background mode using a separate COG" to portray the ordinary n-tasks or n-programs operating concurrently, on "one processor" (although 8 in PChip reality), in a shared resource environment. I'm just not sure if that can be taken at face value, or whether it should be viewed (somewhat) metaphorically. Here's what I mean by that.

    If taken at face value - how, when or where does the actual differentiation or assignment of foreground versus background task/program designation occur, or is it just a mother-and-daughter situation with the first task loaded and executed automatically assuming the role of a forground task (mother), and any further tasks (new COGs started) which are "spawned" becoming de-facto background task (daughters)?

    Moreover, I can only presume there is no inherent prioritization or sequence management, other than that which the 0-1-2-3-4-5-6-7 hub-cog physical or "rotational" sequence might afford, unless self-managment is afforded by sophisticated programming techniques at the user level?

    TIA

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    <!--StartFragment -->
  • GadgetmanGadgetman Posts: 2,436
    edited 2006-03-08 09:42
    Stop thinking about 'foreground' and 'background'.

    All the COGs have the same priority, the same access to the core, the same possibility to start and shut down other COGs, so any 'master' or 'foreground' definition is just by preference.
    Foreground/Background, Master/Slave all indicates higher priority or a one-way command-structure, but that is only useful on a single-processor/multitasking or a master/multiple slaves setup, and this is a multi-processor/cooperative setup.

    From what I understand, you could have COG0 running as the 'primary process', while COG1 is loading a new program, then, when COG1 is ready, COG0 shuts down and frees itself to be reused for later tasks.
    Did someone say instant switches in 'state-machines'?

    Or you could use the 'classic' approach and have the ' primary process' running in one COG and swap in and out useful programs(VGA driver, Serial comms, SPI, 1Wire, and so on) in the other 7 COGs as you need them.
    If done right, they don't even need to be started in the same COG every time, either, just the first free one.

    In fact, if you have a book on multi-processing, its best use today would be as tinder the next time you go camping, or to show your grandchildren so that they have something to laugh about...
    ('Kids, this is how they tried to do it before the Propeller, silly isn't it?')

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Don't visit my new website...
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-08 15:53
    Dave:
    Your examples are great! Not withstanding the issue of formatting, both versions posted provide a crystal clear view of what the object of the "lesson" is.
    For all of the code posters, please, don't stop! You do relize you are not only introducting SPIN code, but intorduction to the Objects you have created as well.

    Thanks guys; for all of you are feeding this very hungry appite for information!

    [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2006-03-08 16:14
    Bruce Bates,

    Did not mean to confuse the issue with foreground/background. It is mostly a reference to the specific function, in this case RCTIME.
    In foreground what I mean is that this command works like a one shot single processor line by line execution. In background mode,
    RCTIME gets it's very own "daughter" processor so you are not confined to wait in the "mother" processor for RCTIME to finish.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-08 16:52
    ·EXAMPLE 07

    CHECKS FOR A HIGH ON PIN A1; HAS VIDEO OUTPUT
    '                                           EXAMPLE07
    '
    '                           CHECKS FOR A HIGH ON PIN A1; HAS VIDEO OUTPUT                     
    '**************************************************************************************
    'IMPORTANT: This example requires an understanding of examples 01 and 03.
    '**************************************************************************************
    'WHAT'S NEW IN THIS EXAMPLE:
    '
    '   If-Else statement: This statement operates the same as If-Else statements in most
    '                      other languages.  Be careful because Spin is indention sensitive.
    '                      Note the indention in the code.
    '
    '   DirA[noparse][[/noparse]1] := In      Sets the direction of Pin A1 to Input. BE CAREFUL TO NOT EXCEED
    '                      3.3 VOLTS.  (A maximum input voltage has not been established at
    '                      this time.)
    '
    '   VideoDisplay.Out(3): This combination of statements will produce white on red.
    '   VideoDisplay.Out(7)
    '
    '   Repeat statement: "Repeat" in this example is an infinite loop. This causes the program
    '                     to constantly check for a High on Pin A1. You must indent
    '                     properly for this to work as desired.
    '**************************************************************************************
    'DIFFICULTY LEVEL: Very Easy
    '
    'MAIN PURPOSE:
    '  -- Demonstrates how to check for a High on an Input Pin.
    '
    'ADDITIONAL INFORMATION: 
    '  -- The video signal output is a composite signal.
    '  -- TV_Terminal is an object call TV_Terminal.spin found in the "Propeller Tool"
    '     subdirectory.
    '  -- Any name could have been used instead of "VideoDisplay"
    '  -- This example assumes you have the development kit or a schematic of it.  
    '     You will need one of these to generate a composite video out.
    '  -- USE A 10K PULL-DOWN RESISTER TO KEEP PIN A1 FROM FLOATING: Place a 10K resistor
    '     between Pin A1 and Vss.
    '  -- This example only uses one Cog.
    '
    'Submitted by Dave Scanlan, March 8, 2006          
    'File: Example07_ReadingAnInputPort.spin
    '***********************************************************************************
    'CORRECT OUTPUT: If Pin A1 is High the following happens:
    '                  (1) The message "INPUT AT PIN A1" is repeatedly displayed on the
    '                      monitor.
    '                  (2) The monitor's foreground and background become white-on-blue.
    '                  (3) The LED at A16 is turned on.
    '
    '                If Pin A1 is Low the following happens:
    '                  (1) The message "NO INPUT" is repeatedly displayed on the monitor.
    '                  (2) The monitor's foreground and background become white-on-red.
    '                  (3) The LED at A16 is turned off.
    '
    'NOTE: USE A 10k PULL-DOWN RESISTER TO KEEP PIN A1 FROM FLOATING: Place a 10K resistor
    '      betweein Pin A1 and Vss.
    '**************************************************************************************
    '
    CON
      _clkmode = xtal1 + pll16x       
      _xinfreq = 5_000_000
      NewLine = 13
      High = 1
      Low = 0
      Out = %1
      In = %0
    '
    VAR
    '  No gobal variables in this program
    '  
    OBJ
      VideoDisplay: "TV_Terminal"               'Creates the object VideoDisplay
    '
    PUB Start                                   'Any name will do here: Start, Begin, Main, etc.
      VideoDisplay.Start                        'Initializes the VideoDisplay object                                                
      CheckForInput
    '  
    PRI CheckForInput
    '
      DirA[noparse][[/noparse]1]  := In                            'Sets Pin A1 to Input
      DirA[noparse][[/noparse]16] := Out                           'Sets Pin A16 to Output
    '
      Repeat                                    'An infinite loop. Indention is important
    ' 
        If InA[noparse][[/noparse]1] == High                       'Be sure to indent under the If 
          SetScreenToWhiteOnDarkBlue
          VideoDisplay.str(String("INPUT AT PIN A1"))
          OutA[noparse][[/noparse]16] := High
        Else                                    'Be sure to indent under the Else
          SetScreenToWhiteOnRed
          VideoDisplay.str(String("NO INPUT"))
          OutA[noparse][[/noparse]16] := Low
    '     
        VideoDisplay.out(NewLine)
    '
    PRI SetScreenToWhiteOnDarkBlue              'This combination of Out's sets the monitor 
      VideoDisplay.Out(3)                       ' to display white-on-blue
      VideoDisplay.Out(5)
    '
    PRI SetScreenToWhiteOnRed                   'This combination of Out's sets the monitor
      VideoDisplay.Out(3)                       ' to display white-on-red.
      VideoDisplay.Out(7)                         
    '
    '
    'INDENTION IS IMPORTANT IN SPIN.
    '
    


    ··FEWER COMMENTS (EASIER TO READ)

    EXAMPLE 07

    ························· CHECKS FOR A HIGH ON PIN A1; HAS VIDEO OUTPUT····················

    '                                FEWER COMMENTS (EASIER TO READ)
    '
    '                                           EXAMPLE07
    '
    '                           CHECKS FOR A HIGH ON PIN A1; HAS VIDEO OUTPUT                     
    '**************************************************************************************
    'IMPORTANT: This example requires an understanding of examples 01 and 03.
    '**************************************************************************************
    'DIFFICULTY LEVEL: Very Easy
    '**************************************************************************************
    'CORRECT OUTPUT: If Pin A1 is High the following happens:
    '                  (1) The message "INPUT AT PIN A1" is repeatedly displayed on the
    '                      monitor.
    '                  (2) The monitor's foreground and background become white-on-blue
    '                  (3) The LED at A16 is turned on
    '
    '                If Pin A1 is Low the following happens:
    '                  (1) The message "NO INPUT" is repeatedly displayed on the monitor
    '                  (2) The monitor's foreground and background become white-on-red
    '                  (3) The LED at A16 is turned off
    '
    'NOTE: USE A 10K PULL-DOWN RESISTER TO KEEP PIN A1 FROM FLOATING: Place a 10K resistor
    '      between Pin A1 and Vss.
    '
    'Submitted by Dave Scanlan, March 8, 2006          
    'File: Example07_FewerComments.spin
    '**************************************************************************************
    '
    CON
      _clkmode = xtal1 + pll16x       
      _xinfreq = 5_000_000
      NewLine = 13
      High = 1
      Low = 0
      Out = %1
      In = %0
    '
    VAR
    '  
    OBJ
      VideoDisplay: "TV_Terminal"               
    '
    PUB Start                                   
      VideoDisplay.Start
      CheckForInput
    '  
    PRI CheckForInput
    '
      DirA[noparse][[/noparse]1]  := In                            
      DirA[noparse][[/noparse]16] := Out                           
    '
      Repeat                                    
    ' 
        If InA[noparse][[/noparse]1] == High
          SetScreenToWhiteOnDarkBlue
          VideoDisplay.str(string("INPUT AT PIN A1"))
          OutA[noparse][[/noparse]16] := High
        Else
          SetScreenToWhiteOnRed
          VideoDisplay.str(string("NO INPUT"))
          OutA[noparse][[/noparse]16] := Low
    '     
        VideoDisplay.out(NewLine)
    '
    PRI SetScreenToWhiteOnDarkBlue              
      VideoDisplay.Out(3)                       
      VideoDisplay.Out(5)
    '
    PRI SetScreenToWhiteOnRed                   
      VideoDisplay.Out(3)                       
      VideoDisplay.Out(7)                         
    '
    'INDENTION IS IMPORTANT IN SPIN.
    



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    FEEDBACK

    I will appreciate feedback on the following:
    1.· Are the examples helpful?
    2.· Are the examples too simple?





    ··
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-08 17:34
    Kaos,

    Thanks for your feedback.

    My next example will be a simple one on using the keyboard as an input device.

    Dave

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    FEEDBACK

    I will appreciate feedback on the following:
    1.· Are the examples helpful?
    2.· Are the examples too simple?





    ··
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-12 20:41
    ·EXAMPLE 08

    ····························· DISPLAYS KEYBOARD CHARACTERS ON A VIDEO MONITOR
    ·························
    '                                   EXAMPLE 08
    '
    '                    DISPLAYS KEYBOARD CHARACTERS ON A VIDEO MONITOR                          
    '****************************************************************************
    'IMPORTANT: This example requires an understanding of example 04.
    '****************************************************************************
    'WHAT'S NEW IN THIS EXAMPLE:
    '   Keyboard_iso: This is a Spin object that must be used in order to use
    '                 GetKey and Present
    '   GetKey: GetKey will return the code for any key pressed on the keyboard.
    '           Using GetKey, you can display characters on a video monitor.
    '   Present: Returns a TRUE if a keyboard is connected.
    '****************************************************************************
    'DIFFICULTY LEVEL: Very Easy
    '
    'MAIN PURPOSE:
    '  -- Demonstrates how to interface the keyboard to the Propeller and how to
    '     display a key press on a video monitor.
    '
    'ADDITIONAL INFORMATION:
    '  -- A PS/2 keyboard must be properly connected to the Properller.
    '  -- This example assumes you have the development kit or a schematic of it.     
    '  -- This example only uses one Cog (processor).
    '
    'Submitted by Dave Scanlan, March 12, 2006         
    'File: Example08_KeyboardInput.spin
    '****************************************************************************  
    'CORRECT OUTPUT: Keyboard characters will be displayed on a video monitor.
    '**************************************************************************** 
    '
    CON
      _clkmode = xtal1 + pll16x       
      _xinfreq = 5_000_000
      NewLine = 13
      PS2ToProperllerPins_Setup = 6  'See number (1) at the bottom.
      KeyLocks_Setup = %0_000_010    'CapsLock ON: See number (2) at the bottom.
    ' KeyLocks_Setup = %0_000_000    'CapsLock OFF: See number (2) at the bottom.
      AutoRepeat_Setup = %01_01000   'See number (3) at the bottom.
    '
    OBJ
      VideoDisplay: "TV_Terminal"
      KB : "Keyboard_iso"            'Creates an instance of Keyboard_iso called KB
    ' 
    PUB Start
    '
      VideoDisplay.start
      SetScreenToWhiteOnDarkBlue
    ' KB.Startx(PS/2 pins setup, CapsLock ON, .5second delay and 15cps key repeat rate)
      KB.Startx(PS2ToProperllerPins_Setup, KeyLocks_Setup, AutoRepeat_Setup)
      WaitCnt(50_000_000 + Cnt)          'Gives KB.Present time to find the keyboard.
    ' 
      If KB.Present                      'Present is true if a keyboard is connected
        VideoDisplay.str(string("KEYBOARD CONNECTED"))
        VideoDisplay.Out(NewLine)
        Repeat
          VideoDisplay.out(KB.GetKey)    'Waits for keypress. Displays character on
    

                                         ' the video monitor.
      Else
        VideoDisplay.str(string("ERROR: KEYBOARD NOT CONNECTED"))
    '
    PRI SetScreenToWhiteOnDarkBlue                  
      VideoDisplay.out(3)                              
      VideoDisplay.out(5)
      
    'ADDITIONAL INFORMATION:
    '****************************************************************************   
    '(1) 6 is a setup code that will properly match the pins on a PS/2 male 
    '    conector with a PS/2 female connector that is connected to the
    '    the Propeller.  See Keyboard_iso.spin for more pin setup codes.
    '(2) %0_000_010 is a setup code that will set CapsLock ON (bit 1). See 
    '    Keyboard_iso for more KeyLock setup settings, such as NumLock and
    '    ScrollLock.
    '(3) %01_01000 is a setup code that will produce a .5sec (bit 5) delay before
    '    auto repeat starts and a 15cps repeat rate (bit 3). See Keyboard_iso
    '    for more setup settings.
    '****************************************************************************
    


    ·FEWER COMMENTS (EASIER TO READ)

    EXAMPLE 08

    ·················· DISPLAYS KEYBOARD CHARACTERS ON A VIDEO MONITOR
    ·························
    '                         FEWER COMMENTS (EASIER TO READ)
    '
    '                                    EXAMPLE 08
    '
    '                    DISPLAYS KEYBOARD CHARACTERS ON A VIDEO MONITOR                          
    '****************************************************************************
    'IMPORTANT: This example requires an understanding of example 04.
    '****************************************************************************
    'DIFFICULTY LEVEL: Very Easy    
    '****************************************************************************  
    'CORRECT OUTPUT: Keyboard characters will be displayed on a video monitor.
    'Submitted by Dave Scanlan, March 12, 2006         
    'File: Example08_FewerComments.spin
    '**************************************************************************** 
    '
    CON
      _clkmode = xtal1 + pll16x       
      _xinfreq = 5_000_000
      NewLine = 13
      PS2ToProperllerPins_Setup = 6  
      KeyLocks_Setup = %0_000_010  'CapsLock ON
    ' KeyLocks_Setup = %0_000_000  'CapsLock OFF
      AutoRepeat_Setup = %01_01000   
    '
    OBJ
      VideoDisplay: "TV_Terminal"
      KB : "Keyboard_iso"              
    ' 
    PUB Start
    '
      VideoDisplay.start
      SetScreenToWhiteOnDarkBlue
    '
      KB.Startx(PS2ToProperllerPins_Setup, KeyLocks_Setup, AutoRepeat_Setup)
      WaitCnt(50_000_000 + Cnt)
    ' 
      If KB.Present                      
        VideoDisplay.str(string("KEYBOARD CONNECTED"))
        VideoDisplay.Out(NewLine)
        Repeat
          VideoDisplay.out(KB.GetKey)
      Else
        VideoDisplay.str(string("ERROR: KEYBOARD NOT CONNECTED"))
    '
    PRI SetScreenToWhiteOnDarkBlue                  
      VideoDisplay.out(3)                              
      VideoDisplay.out(5)
    ' 
    'INDENTION IS IMPORTANT IN SPIN
    

    Post Edited (Dave Scanlan) : 3/13/2006 8:48:06 AM GMT
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-13 17:04
    ·EXAMPLE 09

    DEBUGGING USING·A VIDEO MONITOR
    ·
    '                                      EXAMPLE 09
    '
    '                           DEBUGGING USING THE VIDEO MONITOR                                 
    '****************************************************************************
    'IMPORTANT: This example requires an understanding of example 04.
    '****************************************************************************
    'WHAT'S NEW IN THIS EXAMPLE:
    '
    '  VideoDisplay.Dec(Value):  Dec(Value) will output any Byte, Word, or Long
    '                            as a decimal value.
    '
    '  VideoDisplay.Hex(Value,#OfDigits): Hex(Value,#OfDigits) will output any 
    '                                     Byte, Word, or Long in a Hex format 
    '                                     using a specified number of digits.
    '
    '  VideoDisplay.Bin(Value,#OfDigits): Bin(Value,#OfDigits) will output any
    '                                     Byte, Word, or Long in a Binary format
    '                                     using a specified number of digits.    
    '****************************************************************************
    'DIFFICULTY LEVEL: Very easy
    '
    'PURPOSE:
    '  -- Demonstrates how to display on a video monitor the value of any variable
    '     during program execution.  It further demonstrates how to monitor the
    '     state (HIGH or LOW) of any input port.
    '
    'Submitted by Dave Scanlan, March 13, 2006         
    'File: Example09_DebuggingUsingTheVideoMonitor.spin
    '****************************************************************************
    'CORRECT OUTPUT: The values of three variables are displayed on the video
    '                monitor in Decimal, Hex, and Binary format.
    '                After 10 seconds, Pin A1 is monitored and its state is 
    '                displayed on the video monitor.
    '****************************************************************************
    '
    CON
      _clkmode = xtal1 + pll16x       
      _xinfreq = 5_000_000
      NewLine = 13
      Out = %1
      In = %0
    '
    VAR
      Word Value
    '
    OBJ
      VideoDisplay: "TV_Terminal"                   
    '
    PUB Start
      VideoDisplay.start             'Initialize VideoDisplay Object
      SetScreenToWhiteOnDarkBlue
      DirA[noparse][[/noparse]1] := In                  'Set port A1 to Input
    '
     'DISPLAYS VALUE AS DECIMAL
      Value := 500
      VideoDisplay.Dec(Value)         'Displays a decimal value
      'Output on the video monitor:
      '500
      VideoDisplay.Out(NewLine)
    ' 
     'DISPLAYS VALUE AS HEX
      Value := $FF
      VideoDisplay.Hex(Value,2)       'Displays a hex value using 2 digits
      'Output on the video monitor:
      'FF
      VideoDisplay.Out(NewLine)
    '
     'DISPLAYS VALUE AS BINARY
      Value := %0001_0001
      VideoDisplay.Bin(Value,8)       'Displays a binary value using 8 digits
      'Output on the video monitor:
      '00010001
      VideoDisplay.Out(NewLine)
    '
      WaitCnt(1_000_000_000 + Cnt)    'Keeps output on the screen for 10 seconds.
    ' 
     'MONITORS Pin A1
      Repeat                          'Continuously monitors the state of pin A1
        VideoDisplay.Bin(InA[noparse][[/noparse]1],1)
        VideoDisplay.Out(NewLine)
        'Output on the video monitor:
        '0 or 1  depending on input state at pin A1
        '0 or 1  depending on input state at pin A1
        '0 or 1  depending on input state at pin A1
        '0 or 1  depending on input state at pin A1
        '0 or 1  depending on input state at pin A1
        '...
    '
    PRI SetScreenToWhiteOnDarkBlue                  
      VideoDisplay.out(3)                           
      VideoDisplay.out(5)
    '
    '
    'ADDITIONAL INFORMATION: 
    '  -- The video signal output is a composite signal.
    '  -- TV_Terminal is an object call TV_Terminal.spin found in the
    '     "Propeller Tool" subdirectory.                    
    '  -- Any name could have been used instead of "VideoDisplay"
    '  -- This examples requires an elementary knowledge of OOP.
    '  -- This example assumes you have the development kit or a schematic of it.  
    '     You will need one of these to generate a composite video out.
    


    FEWER COMMENTS (EASIER TO READ)

    EXAMPLE 09

    DEBUGGING USING A VIDEO MONITOR
    '                             FEWER COMMENTS (EASIER TO READ)
    '
    '                                      EXAMPLE 09
    '
    '                           DEBUGGING USING THE VIDEO MONITOR                                 
    '****************************************************************************
    'IMPORTANT: This example requires an understanding of example 04.
    '****************************************************************************
    'CORRECT OUTPUT: The values of three variables are displayed on the video
    '                monitor in Decimal, Hex, and Binary format.
    '                After 10 seconds, Pin A1 is monitored and its state is 
    '                displayed on the video monitor.
    '
    'Submitted by Dave Scanlan, March 13, 2006         
    'File: Example09_FewerComments.spin
    '****************************************************************************
    '
    CON
      _clkmode = xtal1 + pll16x       
      _xinfreq = 5_000_000
      NewLine = 13
      Out = %1
      In = %0
    '
    VAR
      Word Value
    '
    OBJ
      VideoDisplay: "TV_Terminal"                   
    '
    PUB Start
    '
      VideoDisplay.start             
      SetScreenToWhiteOnDarkBlue
      DirA[noparse][[/noparse]1] := In                  
    '
      'DISPLAYS VALUE AS DECIMAL
         Value := 500
         VideoDisplay.Dec(Value)      
         VideoDisplay.Out(NewLine)
    ' 
      'DISPLAYS VALUE AS HEX
         Value := $FF
         VideoDisplay.Hex(Value,2)    
         VideoDisplay.Out(NewLine)
    '
      'DISPLAYS VALUE AS BINARY
         Value := %0001_0001
         VideoDisplay.Bin(Value,8)    
         VideoDisplay.Out(NewLine)
    '
      WaitCnt(1_000_000_000 + Cnt)    
    ' 
      'MONITORS Pin A1
         Repeat                       
           VideoDisplay.Bin(InA[noparse][[/noparse]1],1)
           VideoDisplay.Out(NewLine)
    '
    PRI SetScreenToWhiteOnDarkBlue                  
      VideoDisplay.out(3)                           
      VideoDisplay.out(5)
    

    
    

    Post Edited (Dave Scanlan) : 3/13/2006 5:46:56 PM GMT
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-14 21:11
    Dave:
    I love reading your code. Quick Question: I notice you are constantly changing the video back & forground colors. Can the video object be custome coded to have that as a default, or is the entire object in asm?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2006-03-14 21:37
    Kaos Kidd,
    You said...

    ...Can the video object be custome coded to have that as a default, or is the entire object in asm?...

    Yes, it doesn't matter if the object is in Spin or Asm.... since it is open source and you have access to it, you can
    modify/customize/hack it however you want.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-14 23:32
    Dave:
    I love reading your code. Quick Question: I notice you are constantly changing the video back & forground colors. Can the video object be custome coded to have that as a default, or is the entire object in asm? 
    
    
    

    Hi Kaos,

    Thanks for the kind words about my code.· Beau did a great job answering your question.· Sometime when I get extra time I will make·white on blue·the default for the foreground and background colors.

    Thanks,

    Dave

    Post Edited (Dave Scanlan) : 3/15/2006 12:28:29 AM GMT
  • Dave ScanlanDave Scanlan Posts: 160
    edited 2006-03-15 18:45
    ·EXAMPLE 10


    HOW TO CODE A FUNCTION THAT FINDS THE LARGEST OF TWO VALUES
    ····················
    '
    '
    '                                     EXAMPLE 10
    '
    '            HOW TO CODE A FUNCTION THAT FINDS THE LARGEST OF TWO VALUES                      
    '*********************************************************************************  
    'IMPORTANT: This example may require an understanding of examples 04, 05, and 06.
    '*********************************************************************************
    'WHAT'S NEW IN THIS EXAMPLE:
    '
    '     FUNCTION: A function is a type of procedure that returns a value. A function
    '               is often called a function procedure.
    '
    '*********************************************************************************  
    'DIFFICULTY LEVEL: Intermediate
    '
    'PURPOSE: This code demonstrates how to code a function.  This function will return
    '         the largest of two values.
    '
    'Submitted by Dave Scanlan, March 15, 2006         
    'File: Example10_FunctionFindLargestVer1.spin
    '*********************************************************************************
    'CORRECT OUTPUT:  The largest value (10) will be displayed on the video monitor.
    '*********************************************************************************
    CON
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
    ' 
    VAR
    'No global variables used.
    '
    OBJ
      VideoDisplay: "TV_Terminal"            
    '
    PUB Start | X, Y, LargestValue        'X, Y, and LargestValue are Local variables.
      VideoDisplay.Start
      SetScreenToWhiteOnDarkBlue
    '
      X := 5
      Y := 10
    ' 
      LargestValue := FindTheLargest(X,Y) 'Calls the function and assigns the
    '                                      result to "LargestValue."
      VideoDisplay.Dec(LargestValue)
    '
    PRI FindTheLargest (X,Y) | Largest     'Declares the function.
      If X > Y
        Largest := X
      Else
        Largest := Y
    '
      Result := Largest                    '"Result" is a Spin reserved word and is the 
    '                                        location use to return the result of the 
    '                                        function.
    PRI SetScreenToWhiteOnDarkBlue                  
      VideoDisplay.Out(3)                           
      VideoDisplay.Out(5)
    '
    '
    'ADDITIONAL INFORMATION ON HOW THIS FUNCTION WORKS:
    '  PRI FindTheLargest (X,Y)
    '     -- This is the declaration of the function called "FindTheLargest".
    '     -- The X and Y are parameters.
    '     -- The Spin reserved word "Result" is a location used to return
    '        the result of the function.
    '
    '  LargestValue := FindTheLargest(X,Y)
    '    -- This statement calls the function and passes the arguments, X(5)and Y(10),
    '       to their corresponding parameters in the function.
    '    -- The code in the function is executed and the result is stored in
    '       the location called "Result"
    '    -- In the final step, the value stored in the location called "Result"  
    '       is assigned to "LargestValue" although this final step is not obvious.
    '       A way to conceptualize the assignment is: LargestValue := Result.
    


    FEWER COMMENTS (EASIER TO READ)

    EXAMPLE 10

    HOW TO CODE A FUNCTION THAT FINDS THE LARGEST OF TWO VALUES
    '                                      EXAMPLE 10
    '
    '            HOW TO CODE A FUNCTION THAT FINDS THE LARGEST OF TWO VALUES                      
    '*********************************************************************************  
    'IMPORTANT: This example may require an understanding of examples 02 through 06.
    '*********************************************************************************
    'DIFFICULTY LEVEL: Intermediate
    '*********************************************************************************                           
    'CORRECT OUTPUT:  The largest value (10) will be displayed on the video monitor.
    'Submitted by Dave Scanlan, March 15, 2006         
    'File: Example10_FewerComments.spin
    '*********************************************************************************
    CON
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
    ' 
    OBJ
      VideoDisplay: "TV_Terminal"            
    '
    PUB Start | X, Y, LargestValue       
      VideoDisplay.Start
      SetScreenToWhiteOnDarkBlue
    '
      X := 5
      Y := 10
      LargestValue := FindTheLargest(X,Y)                                      
      VideoDisplay.Dec(LargestValue)
    '
    PRI FindTheLargest (X,Y) | Largest    
      If X > Y
        Largest := X
      Else
        Largest := Y
      Result := Largest                    
                                         
    PRI SetScreenToWhiteOnDarkBlue                  
      VideoDisplay.Out(3)                           
      VideoDisplay.Out(5)
    

    Post Edited (Dave Scanlan) : 3/19/2006 3:22:59 AM GMT
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2006-03-15 19:11
    Let me share a trick (in PBASIC, but works in·Spin too)·that our friend Tracy Allen taught me -- very elegant, indeed:


    PUB lowval(x, y)

    ·
    · result := x <# y·
    ·

    PUB highval(x, y)
    ·
    · result := x #> y

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax

    Post Edited (Jon Williams (Parallax)) : 3/15/2006 7:42:33 PM GMT
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-03-15 19:29
    Ive been playing with those operators, my other fav's are |< and >|.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·1+1=10
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2006-03-15 19:38
    I love that trick, and in Spin it even works properly with negative values, i.e.:

    · lowval(-3, -1)

    returns -3.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2006-03-15 20:09
    Here is another way you can use "#>" and "<#" to create a specific range to limit a value's Upper and Lower limit.

    Value := LowerLimit #> Value <# UpperLimit
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-16 19:36
    Thanks Dave and Beau for the answers.
    Man do I have some highly required reading to do.
    Oh, and where do you guys fild the refs on thes #> and <# operators... the PBasic manual? I haven't looked for them yet, but once gain I'm seeing short hand that I'd like to get to know better. An example the Var += 1 (increment the var by 1)... where is that shortcut listed at? Are there others about ?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-03-16 19:54
    They are all spin operators, some have analogs in PBASIC but some don't. Almost every operator in spin has an equivalent assignment operator which takes the result variable and uses it as the argument variable. So X = X + 1 becomes X += 1, X = X * Y becomes X *= Y, etc.

    Here is a summery of the Spin operators and thier equivalent assignment operators: http://www.parallax.com/dl/docs/prod/prop/SpinElements.pdf#page=6

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·1+1=10
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2006-03-16 20:11
    Kaos Kidd,

    If you are just incrementing or decrementing by 1 then you can use...

    Variable++
    
    


    or
    Variable--
    
    



    ...otherwise, you can use something like this...


    Variable += 5
    
    


    or
    Variable -= 5
    
    



    ...to increment or decrement a value.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-17 16:43
    Paul: THanks for the link. It was informative... Now to remember all that when I start coding for the propeller.
    Beau: That's the english I was asking for [noparse]:)[/noparse] The link Paul gave me also explained it, just not as well.

    When using the short hand operators, does it decrease the actual spin code size that's downloaded? Or, is that optimized as compile time?
    Also, other then reducing some readability ( VAR += 5 is not as self explanatory as VAR = VAR + 5 ), what are the benifits of using short hand operators?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2006-03-17 17:23
    Kaos Kidd -

    There are lots of answers to your question, but only one honest one smile.gif

    This permits the software (compiler, interpreter, etc) to use Polish Notation and/or arithmetic stacks directly.
    Oops, the "secret" is out smile.gif

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    <!--StartFragment -->
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-03-17 18:43
    [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Just tossing my two bits worth into the bit bucket


    KK
    ·
Sign In or Register to comment.