{{12 Sep 09   Harprit Sandhu
BlinkLED.spin
Propeller Tool Ver. 1.2.6
Chapter 02 Prog 01

This program turns an LED ON and OFF, with a programmable delay
It demonstrates the use of methods in an absolutely minimal way.
Since the clock is 10 MHz

Define the constants we will use.

}}
CON        
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the crystal frequency

  inv_high      =0               'define the inverted High state
  inv_low       =1               'define the inverted Low state
  waitPeriod    =6_000_000       'about 1/2 sec switch cycle
  output_pin    =27              'line the led is on
 
'High is defined as 0 and low is defined as a 1 because we are using an
'inverting buffer on the Propeller output

PUB Go                  
  dira [output_pin]~~           'sets pin to an output line with ~~ notation
  outa [output_pin]~~           'makes the pin high
  repeat                        'repeat forever, no number after repeat
     turnOff_LED                'method call
     wait                       'method call
     turnOn_LED                 'method call
     wait                       'method call
 
PRI turnOn_LED                  'method to set the LED line high
    outa[output_pin] :=inv_high 'line that actually sets the LED high
                                      
PRI turnOff_LED                 'method to set the LED line low
    outa[output_pin] :=inv_low  'line that actually sets the LED low
                          
PRI wait                        'delay method
    waitCnt(waitPeriod + cnt)   'delay is specified by the waitPeriod






{{ Aug 31 09      Harprit Sandhu
FreqGen8.Spin  
Propeller Tool Ver. 1.2.6
Chapter 03 Prog 01
             
This program generates 8 frequencies starting at 440 cycles/sec.
Depends on the position of Pot 1

}}
CON                                                                     
  _CLKMODE=XTAL1+ PLL2X      'The system clock spec
  _XINFREQ = 5_000_000       'Crystal freq
  Output     = 26            'output line for the speaker
  Repfactor  = 100           'number of times to toggle line
 
VAR
{RAM assignment for cogs}                                           
  long  Stack1[50]       'this RAM will be assigned to COG1
  long  Stack2[50]       'this RAM will be assigned to COG2

{variables used for reading pot}
  word  PotValue         'value of the pot reading 
  long  NoteFreq         'actual frequency of the note
  long  NoteDelay        'delay in cycles
 
{variables used in displaying LCD in Cog2}
  'none           

{variables used in GetTone}
  Byte  toneNumber
 
OBJ                             'The Objects we will need for our calls
  LCD  : "LCDRoutines4"         'for controlling the LCD
  UTIL : "Utilities"            'for general methods

DAT
  Tone word 440, 494, 523, 587, 659, 698, 784, 880
 
PUB GO                          'The main method in this program
                                'the potentiometer is read in this cog
  cognew (COG_LCD,   @Stack1)   'create COG_TWO for LCD display                                       
  cognew (COG_PLAY,  @Stack2)   'create COG_THREE for toggling output
  repeat                        'start repeat loop
    PotValue:=UTIL.Read3202_0       'get potValue from the utilities
    ToneNumber:=Potvalue/512 +1     'This reduces the value to 0-15  
  
PRI COG_LCD                        'Handles display  to the LCD                                                                                                                                                                                                                       
  LCD.INITIALIZE_LCD               'set up the LCD              
  REPEAT                           'repeat write to the LCD                   
     LCD.POSITION (1,1)            'Go to 1st line 1st space
     LCD.PRINT(STRING("PotPos =")) 'Potentiometer position
     LCD.PRINT_DEC(ToneNumber)     'print the tune number     
     LCD.SPACE(2)                  'erase over overflows
     LCD.POSITION (2,1)            'Go to 2nd line 1st space
     LCD.PRINT(STRING("FreqOut=")) 'frequency label printed
     LCD.PRINT_DEC(NoteFreq)       'print note cps     
     LCD.SPACE(2)                  'erase over overflows
                                                        
PRI COG_PLAY                       'output for speaker   
  dira[Output]~~                   'output pin
  repeat                           'outer loop
    repeat RepFactor               'inner loop and repeat #
      GetTone                      'gets value for NoteFre 
      !OUTA[output]                'toggle output line
      NoteDelay:=12_000_000/(NoteFreq*2)   'calculate the delay
      waitcnt(NoteDelay +cnt)       'wait for delay to synthesize freq
    waitcnt(clkfreq/2+cnt)

                              
PUB GetTone                       'gets the frequency to be played
  NoteFreq := Tone[toneNumber-1]  'looks up position in DAT statements





{{12 Sep 09   Harprit Sandhu
BlinkLED.spin
Propeller Tool Ver. 1.2.6
Chapter04 Program 01

This program turns an LED ON and OFF, with a programmable delay
It demonstrates the use of methods in an absolutely minimal way.
Since the clock is 10 MHz

Define the constants we will use.

}}
CON        
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the crystal frequency

  inv_high      =0               'define the inverted High state
  inv_low       =1               'define the inverted Low state
  waitPeriod    =6_000_000       'about 1/2 sec switch cycle
  output_pin    =27              'line the led is on
 
'High is defined as 0 and low is defined as a 1 because we are using an
'inverting buffer on the Propeller output

PUB Go                  
  dira [output_pin]~~           'sets pin to an output line with ~~ notation
  outa [output_pin]~~           'makes the pin high
  repeat                        'repeat forever, no number after repeat
     turnOff_LED                'method call
     wait                       'method call
     turnOn_LED                 'method call
     wait                       'method call
 
PRI turnOn_LED                  'method to set the LED line high
    outa[output_pin] :=inv_high 'line that actually sets the LED high
                                      
PRI turnOff_LED                 'method to set the LED line low
    outa[output_pin] :=inv_low  'line that actually sets the LED low
                          
PRI wait                        'delay method
    waitCnt(waitPeriod + cnt)   'delay is specified by the waitPeriod
                         





{Chapter 7  Program 1  }

PRI
repeat                             'power PWM routine.
   phsa:=PulseWidth                'Send a high pulse for PulseWidth counts
   period:=period + Cycle_time     'Calculate cycle time
   waitcnt(period)                 'Wait for the cycle time





{{14 Sep 09   Harprit Sandhu
PWM.spin
Propeller Tool Ver 1.2.6
Chapter 07 Program 02

This program generates a fixed PWM. Meaning that as programmed
the width does not vary. (Set at 50%) It is easy to recognise
}}
    
CON                                   
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          'crystal frequency
 
VAR       
  long pulsewidth           '
  long cycle_time           '
  long period               '
                            '
PUB Go
  dira[7]~~                            'set output line
  ctra[30..26]:=%00100                 'run PWM mode
  ctra[5..0]:=7                        'Set the "A pin" of this cog 
  frqa:=1                              'Set this counter's frqa value to 1
  PulseWidth:=-5000                    'Start with position=5_000
  Cycle_time:=clkfreq/1000             'Set the time for the pulse width to 1 ms
  period:=cnt                          'Store the current value of the counter
  repeat                               'PWM routine.
    phsa:=PulseWidth                   'Send a high pulse for PulseWidth counts
    period:=period + Cycle_time        'Calculate cycle time
    waitcnt(period)                    'Wait for the cycle time





{{14 Sep 09   Harprit Sandhu
PWM1.spin
Propeller Tool Ver 1.2.6
Chapter 07 Progarm 03

This program generates a variable PWM signal.
Based on a potentiometer reading
}}
    
CON                                   
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          'crystal frequency
 
VAR
  long stack1[25]               'space for motor
  long stack2[25]               'space for LCD        
  long pulsewidth               '
  word pot                      '
OBJ
  LCD     : "LCDRoutines4"      'for the LCD methods
  UTIL    : "Utilities"         'for general methods
                       
PUB Go
  cognew(RunMotor(7),@Stack1)
  cognew(LCD_manager,@stack2)
  repeat                           
     Pot:=UTIL.read3202_0              'read the pot at MCP3202  line 0
    
PUB RunMotor(Pin)|Cycle_time,period    'method to toggle the output
  dira[7]~~                            'gain access to these three amplifier lines
  dira[19..20]~                        'potentiometer location
  ctra[30..26]:=%00100                 'Set this cog's "A Counter" to run PWM
  ctra[5..0]:=Pin                      'Set the "A pin" of this cog to Pin  
  frqa:=1                              'Set this counter's frqa value to 1
  PulseWidth:=50                       'Start with position=50
  Cycle_time:=clkfreq/1000             'Set the time for the pulse width to 10 ms
  period:=cnt                          'Store the current value of the counter
  repeat                               'power PWM routine.
    phsa:=-(pot*244/100)               'Send a high pulse for PulseWidth counts
    period:=period+Cycle_time          'Calculate cycle time
    waitcnt(period)                    'Wait for the cycle time to complete
PRI LCD_manager
  LCD.INITIALIZE_LCD                 'initialize the LCD
  repeat                             'LCD loop  
    LCD.POSITION (1,1)               'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot=" ))       'Potentiometer position ID
    LCD.PRINT_DEC(pot)               'print the pot reading 
    LCD.SPACE(5)                     'erase over old data





{Chapter 9  Program 1  }

PRI
  repeat                             'movement loop
    iters:=pot2                      'set number of iterations to perform
    index:=0                         'reset index
    repeat iters                     'do iterations
      index:=index+1                 'increment index                                                           
      targetPosition:=targetPosition+index   'set new position
      waitcnt(clkfreq/Pot1+cnt)              'wait time for iteration
    repeat iters                     'now do the slow down          
      index:=index-1                                                  
      targetPosition:=targetPosition+index
      waitcnt(clkfreq/Pot1+cnt)
    repeat while startFlag==0        'wait till done
    waitcnt(clkfreq+cnt)             'delay to see stop
    targetPosition:=startPosition    'set to go back  
    waitcnt(24_000+cnt)              'wait to get done
    repeat while startFlag==0        'wait till done                                                                         
    waitcnt(clkfreq+cnt)             'delay to see stop





{{04 June 09     Harprit Sandhu
BlinkMethod.spin
Propeller Tool Ver. 1.2.6
Chapter 10 Program 01

Blinking an LED
This program turns an LED ON an OFF and demonstrates the use of subroutines
in an absolutely minimal way.

Define the constants we will use.

Propeller font schematic:

             100 O
        21+---????---??----+
                   LED   
                           ? GND
}}
CON                             'CON defines the constants           
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          'external crystal
                                                       
  pin           =27              'select the pin to be used for the LED
  waitPeriod    =500             'set the wait period       
  high          =1               'define the High state    
  low           =0               'define the Low state
 
{{
The following PUB Go is the main part of the program.
Everything else is in the 3 called Methods
}}

PUB Go                  
  dira [pin]~~                   'sets pin to an output line with the ~~ notation
  repeat                         'specifies times to repeat. Blank=forever
    turnOn_LED                   'these 4 Methods are called by name alone
    wait                         'these 4 Methods are called by name alone
    turnOff_LED                  'these 4 Methods are called by name alone
    wait                         'these 4 Methods are called by name alone
  
PRI turnOn_LED                   'Method to set the LED line high
    outa[pin] :=high             'line that actually sets the LED high
   
PRI turnOff_LED                  'Method to set the LED line low
    outa[pin] :=low              'line that actually sets the LED low
   
PRI wait                         'Method defines the delay
    waitCnt((Clkfreq/1000)*waitperiod +cnt)  'wait till counter reaches this value





{{12 Sep 09   Harprit Sandhu
BlinkLED.spin
Propeller Tool Ver. 1.2.6
Chapter13 Program 1

This program turns an LED ON and OFF, with a programmable delay
It demonstrates the use of methods in an absolutely minimal way.
Since the clock is 10 MHz

Define the constants we will use.

}}
CON        
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the crystal frequency

  inv_high      =0               'define the inverted High state
  inv_low       =1               'define the inverted Low state
  waitPeriod    =6_000_000       'about 1/2 sec switch cycle
  output_pin    =27              'line the led is on
 
'High is defined as 0 and low is defined as a 1 because we are using an
'inverting buffer on the Propeller output

PUB Go                  
  dira [output_pin]~~           'sets pin to an output line with ~~ notation
  outa [output_pin]~~           'makes the pin high
  repeat                        'repeat forever, no number after repeat
     turnOff_LED                'method call
     wait                       'method call
     turnOn_LED                 'method call
     wait                       'method call
 
PRI turnOn_LED                  'method to set the LED line high
    outa[output_pin] :=inv_high 'line that actually sets the LED high
                                      
PRI turnOff_LED                 'method to set the LED line low
    outa[output_pin] :=inv_low  'line that actually sets the LED low
                          
PRI wait                        'delay method
    waitCnt(waitPeriod + cnt)   'delay is specified by the waitPeriod
                         




{{11 Sep 09     Harprit Sandhu
LCDminimal.spin
Propeller Tool Ver 1.2.6
Chapter 14  Program 1

PROGRAM TO BEGIN USING THE LCD

A minimal LCD implementation to allow us to use the LCD in our
experiments immediately.

This program is an absolutely minimal implementation to 
make the LCD usable. You can work on improving it. We will improve it later
                                                                                                                           
                                                        +------------+                         
Schematic                                               +--------+                          
                                                        +----+                          
                                                                                     
POWER ETC:          +----------------------------------------+                            
BASIC CONNECTIONS   1 0 9 8 7 6 5 43 X X G3 2 1 0 9 8 7 6                            
FOR THE EDUCATION                                                                     
KIT ARE STANDARD        Propeller               CHIP                                  
CONNECTIONS AND ARE 0 1 2 3 4 5 6 7G B R 38 9 0 1 2 3 4 5                            
NOT SHOWN HERE      +----------------------------------------+                            
                                                                           
                                        +-----+-+-+-+-+-+-+-+----+-+-+                         
                                        +---+-+-+-+-+-+-+-+----+-+                           
                                  5VDC  +-+-+-+-+-+-+-+-+----+                             
                                    ?                                     
                                                                         
                                                                         
                       +----------?-+-+                                   
                                                                   
                            +-------------------------------------------------+               
                                G 5 G S W E 0 1 2 3 4 5 6 7                                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                            +-------------------------------------------------+               
                             16 CHAR BY 2 LINE LCD DISPLAY                                    
                       ? GND  8 BIT MODE                   

Revisions


Pin assignment are assigned as constants because the pins are fixed.
These numbers reflect the actual wiring on the board between the Propeller
and the 16x2 LCD display. If you want the LCD on other lines, that would
have to be specified here.  We are going to use 8 bit mode to transfer data for
now.  All these numbers refer to lines on the Propeller
}}

CON      
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the crystal frequency

  RegSelect     = 16                
  ReadWrite     = 17                 
  Enable        = 18   
  DataBit0      = 8    
  DataBit7      = 15
  waitPeriod    =500_000                  'set the wait period
  high          =1                        'define the High state
  low           =0                        'define the Low state
{{
Defining high and low states will allow us to invert these when we use
buffers to amplify the output from the prop chip.  We will then make
low=1 and high=0 thus inverting all the values throughout the program 
}}

PUB Go                        
  DIRA[DataBit7..DataBit0]:=%11111111  'the lines for the LCD are outputs
  DIRA[RegSelect] := High         'the lines for the LCD are outputs
  DIRA[ReadWrite] := High         'the lines for the LCD are outputs
  DIRA[Enable]    := High         'the lines for the LCD are outputs

  INITIALIZE_LCD                  'initialize the LCD
  waitcnt(1_000_000+cnt)          'wait for LCD to start up
  CLEAR                           'clear the LCD
  repeat 4                        'print 4 'A's
    SEND_CHAR ("A")                                                                                              
  repeat 4                        'print 4 'a's
    SEND_CHAR ("b")                                                                                              
  POSITION (1,2)                  'move to POSITION: line 2, space 1
  repeat 4                        'print 4 'B's
    SEND_CHAR ("C")                                                                                              
  repeat 4                        'print 4 'b's
    SEND_CHAR ("d")                                                                                              
  repeat                          'this is a parking loop to keep the system
                                  'from shutting down. It just loops here
                                  'see what cursor does if it is omitted
                                                                                                                 
PRI INITIALIZE_LCD                'The addresses and data used here are
  waitcnt(500_000+cnt)            'specified in the Hitachi data sheet for
                                  'display. YOU MUST CHECK THIS FOR YOURSELF
  OUTA[RegSelect] := Low          'these three lines are specified to write
  OUTA[ReadWrite] := Low          'the initial set up bits for the LCD
  OUTA[Enable]    := Low          'See Hitachi HD44780 data sheet
                                  'display. YOU MUST CHECK THIS FOR YOURSELF.
  SEND_INSTRUCTION (%0011_0000)   'Send 1st
  waitcnt(49_200+cnt)             'wait                              
  SEND_INSTRUCTION (%0011_0000)   'Send 2nd
  waitcnt(1_200+cnt)              'wait               
  SEND_INSTRUCTION (%0011_0000)   'Send 3rd
  waitcnt(12_000+cnt)             'wait                                                                                                               
  SEND_INSTRUCTION (%0011_1000)   'Sets DL=8 bits, N=2 lines, F=5x7 font
  SEND_INSTRUCTION (%0000_1111)   'Display on, Cursor on, Blink on     
  SEND_INSTRUCTION (%0000_0001)   'clear LCD
  SEND_INSTRUCTION (%0000_0110)   'Move Cursor, Do not shift display
                                                                                                                 
PUB CLEAR                          'Clear the LCD display and go home
  SEND_INSTRUCTION (%0000_0001)                                                                                       
                                                                                                                      
PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION    'Position cursor 
  'HOR_POSITION : Horizontal Position : 1 to 16
  'LINE_NUMBER : Line Number : 1 or 2        
  CHAR_LOCATION := (HOR_POSITION-1) * 64  'figure location
  CHAR_LOCATION += (LINE_NUMBER-1) + 128  'figure location
  SEND_INSTRUCTION (CHAR_LOCATION)   'send the instr to position cursor                                                            
                                                
PUB SEND_CHAR (DISPLAY_DATA)   'set up for writing to the display    
  CHECK_BUSY                   'wait for busy bit to clear before sending
  OUTA[ReadWrite] := Low       'Set up to read busy bit
  OUTA[RegSelect] := High      'Set up to read busy bit
  OUTA[Enable]    := High      'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to SEND data in
  OUTA[Enable]    := Low       'Toggle the bit H>L
 
PUB CHECK_BUSY | BUSY_BIT       'routine to check busy bit
  OUTA[ReadWrite] := High       'Set to read the busy bit         
  OUTA[RegSelect] := Low        'Set to read the busy bit
  DIRA[DataBit7..DataBit0] := %0000_0000  'Set the entire port to be an input         
  REPEAT                        'Keep doing it till clear
    OUTA[Enable]  := High       'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]   'the busy bit is bit 7 of the byte read
    OUTA[Enable]  := Low        'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)         'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit0] := %1111_1111  'set the data port back to outputs
                                           
PUB SEND_INSTRUCTION (DISPLAY_DATA) 'set up for writing instructions
  CHECK_BUSY                   'wait for busy bit to clear before sending
  OUTA[ReadWrite] := Low       'Set up to read busy bit         
  OUTA[RegSelect] := Low       'Set up to read busy bit         
  OUTA[Enable]    := High      'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to READ data in 
  OUTA[Enable]    := Low        'Toggle the bit H>L
          




{{12 Sep 09      Harprit Sandhu
ButtonLED.spin
Propeller Tool 1.2.6
Chapter 15 Prog 01

This program turns an LED ON if an input that has been pulled up is grounded
It demonstrates the use of subroutines in an absolutely minimal way.

First define the constants we will use.

}}
CON                                                                             
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ      = 5_000_000
  input_pin     =23            'select the pin to be used for input
  output_pin    =27            'select the pin to be used for the LED
  inv_high      =0             'define the inverted High state
  inv_low       =1             'define the inverted Low state
 
'High is defined as 0 and low is defined as a 1 because we are using an
'inverting buffer on the output

PUB Go                  
  dira [output_pin]~~   'sets pin to an output line with ~~ notation
  outa [output_pin]~    'makes the pin a low output
  dira [input_pin]~     'sets pin to an input line with the ~ notation
  repeat                'repeat forever because there is no number after repeat
   if ina[input_pin]==0    'check pin for high or low
     turnOn_LED         'subroutine call
   else
      turnOff_LED       'subroutine call
 
PRI turnOn_LED                  'subroutine to set the LED line high
    outa[output_pin] :=inv_high 'line that actually sets the LED high

PRI turnOff_LED                 'subroutine to set the LED line low
    outa[output_pin] :=inv_low  'line that actually sets the LED low





{{Aug 31 09   Harprit Sandhu
ReadPot.spin
Propeller Tool Version 1.2.6
Chapter 16 Prog 01
      
READING A POTENTIOMETER

This routine ready a 10K pot with a 10 mfd cap
This routine is what is used in the utilities to read the pot
Pot is always read from the same line

}}   
CON                                                                 
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          'Crystal spec
  PotLine   = 19          'line the pot it on                 
                               
OBJ
  LCD : "LCDRoutines4"     'We will be using these METHODS in this program

VAR                       'these are the variables we will use.
   long  startCnt         'count at start
   long  endCount         'count at end
   long  delay            'time difference
   long  PotValue         'Value of the pot reading
                                   
PUB Go   
  LCD.INITIALIZE_LCD           'set up the LCD
  repeat                       'loop               
    dira[PotLine]~~            'set potline as output         
    outa[PotLine]~~            'make it high so we can charge the capacitor
    waitcnt(4000+cnt)          'wait for the capacitor to get charged
    dira[PotLine]~             'make potline an input. line switches H>L
    startCnt:=cnt              'read the counter at start of cycle and store
    repeat                     'go into an endless loop                   
    while ina[PotLine]~~       'keep doing it as long as the potline is high
    EndCount := cnt            'read the counter at end of cycle and store
    delay := ((EndCount-StartCnt)-1184)   'calculate time for line to go H>L
    if delay>630000             'max permitted delay
      delay:=630000             'clamp delay
    PotValue:=(delay/2220)      'This reduces the value to 0-255 or 1 byte
    PotValue <#=255             'clamp range
    PotValue #>=1               'clamp range                     
    LCD.POSITION (1,1)            'Go to 1st line 1st space
    LCD.PRINT(STRING("PotPos =")) 'Potentiometer position
    LCD.PRINT_DEC(PotValue)       'print value                                                               
    LCD.SPACE(3)                  'erase over overflows
    LCD.POSITION (2,1)            'Go to 2nd line 1st space
    LCD.PRINT(STRING("Delay  =")) 'Print
    LCD.PRINT_DEC(delay)          'print value                                                               
    LCD.SPACE(3)                  'erase over overflows       





{{11 Sep 09     Harprit Sandhu
Segment
Propeller Tool Ver 1.2.6
Chapter 16  Program 2
}}

PUB GetPotVal                       
  dira[PotLine]~~                'set potline as output
  valutotal:=0                   'clear total                     
    repeat  repval               'repeat                     
      dira[PotLine]~~            'set potline as output         
      outa[PotLine]~~            'make it high so we can charge the capacitor
      waitcnt(4000+cnt)          'wait for the capacitor to get charged
      dira[PotLine]~             'make potline an input. line switches H>L
      startCnt:=cnt              'read the counter at start of cycle and store
      repeat                     'go into an endless loop                   
      while ina[PotLine]~~       'keep doing it as long as the potline is high
      EndCount := cnt            'read the counter at end of cycle and store
      delay := ((EndCount-StartCnt)-1184)   'calculate time for line to go H>L
      if delay>610_000            'max permitted delay
        delay:=610_000            'clamp delay
      PotValue:=(delay/2300)      'This reduces the value to 0-255 or 1 byte
      valutotal:=valutotal+potvalue    'figures total
      potvalue:=valutotal/repval  'figure average  
      potvalue <#=255
      potvalue #>=0            
  result:=PotValue                'figure average





{{03 Nov 09   Harprit Sandhu
MCP3202Read1.Spin
Version 1.00.00
Propeller Tool 1.2.6
Chapter 16 Prog 03

All the code in this program is in SPIN

This program reads channel 0 of the MCP3202 and displays the results
on the LCD both as a decimal value and as a binary value so that you
can see the bits flip as you turn the potentiometer.

The 3202 chip is connected as follows:
1 Chip select                                          P21
2 Channel 0 for voltage input from Pot                 Pot wiper
3 Channel 1 for voltage input from Pot, not used       Ground it
4 Ground Vss                                           Ground
5 Data into 3202 for setup                             P19
6 Data out from 3202 to be read into Propeller         P22
7 Clock to read in the data                            P20
8 Power 5 volts Vdd                                    5 volts

The Potentiometer is connected as follows:
Left    Ground
Center  To pin 2 of the 3202
Right   Power  5 volts
I used a 50K Pot

The connections to the LCD are as follows:
1   Ground
2   Power 5 volts
3   Ground
4   P16
5   P17
6   P18
7   Not connected, using 4 bit mode for data Xfer
8   Not connected, using 4 bit mode for data Xfer
9   Not connected, using 4 bit mode for data Xfer
10  Not connected, using 4 bit mode for data Xfer
11  Data  high nibble
12  Data  high nibble
13  Data  high nibble
14  Data  high nibble

STANDARD EDUCATION KIT SET UP.  Used as base

Revisions:

Error Reporting:
Please report errors to harprit.sandhu@gmail.com

}}
OBJ
  LCD     : "LCDRoutines4" 'for the LCD methods
                                                    
CON                                                                  
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          'crystal spec
   BitsRead =12      
   chipSel  = 19           
   chipClk  = chipSel+1  
   chipDout = chipSel+2  
   chipDin  = chipSel+3
  
VAR
  long stack2[25]
  word PotReading              
  word DataRead
                                                       
PUB Go
  cognew(Cog_LCD, @stack2)
  DIRA[0..7]~                                                                     
  DIRA[chipSel]~~     'osc once to set up 3202                 
  DIRA[chipDin]~~     'data set up to the chip                                    
  DIRA[chipDout]~     'data from the chip to the Propeller     
  DIRA[chipClk]~~     'oscillates to read in data from internals                        
  repeat       
    DataRead:=0             'Clear out old data
    outa[chipSel]~~         'Chip select has to be high to start off                       
    outa[chipSel]~          'Go low to start process
                                  
    outa[chipClk]~          'Clock MUST be low to load data    
    outa[chipDin]~~         'must start with Din high to set up 3202                  
    outa[chipClk]~~         'Clock high to read data in
                                  
    outa[chipClk]~          'Low to load     
    outa[chipDin]~~         'High single mode                 
    outa[chipClk]~~         'High to read
                                          
    outa[chipClk]~          'Low to load              
    outa[chipDin]~          'Odd = low channel 0         
    outa[chipClk]~~         'High to read
                                   
    outa[chipClk]~          'Low to load      
    outa[chipDin]~~         'msbf high = MSB first               
    outa[chipClk]~~         'High to read
   
    outa[chipDin]~          'making line low for rest of cycle   
    outa[chipClk]~          'Low to load Read/discard the null bit
    outa[chipClk]~~         'High to read
  
    repeat BitsRead          'Reads the data into DataRead in 12 steps
      DataRead <<= 1         'Move data by shifting left 1 bit. Ready for next bit
      outa[chipClk]~         'Low to load
      DataRead:=DataRead+ina[chipDout]  'Xfer the data from pin chipDout                          
      outa[chipClk]~~        'High to read                                        
    outa[chipSel]~~          'Put chip to sleep, for low power                     
    PotReading:=DataRead     'Finished data read for display
     
PRI cog_LCD                      'manage the LCD  
  LCD.INITIALIZE_LCD             'initialize the LCD
  repeat    
    LCD.POSITION (1,1)           'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot=" ))   'Print Label
    LCD.PRINT_DEC(PotReading)    'print decimal value
    LCD.SPACE(4)                 'erase over old data      
    LCD.POSITION (2,1)           'Go to 2nd line 1st space
    LCD.PRINT_BIN(PotReading,BitsRead)   'Print it as bits.






{{12 Sep 09    Harprit Sandhu
BlinkLEDpot.spin
Propeller Tool Ver. 1.2.6
Chapter 16 Program 04

This program turns an LED ON and OFF, with a pot set delay

Define the constants we will use
}}
CON        
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the crystal frequency

  inv_high      =0               'define the inverted High state
  inv_low       =1               'define the inverted Low state
  output_pin    =27
 
'High is defined as 0 and low is defined as a 1 because we are using an
'inverting buffer on the Propeller output

VAR
  long   Potvalue
  long   WaitPeriod
  byte   div             'dividing factor for clock freq
 
OBJ                      'These are the methods we will need 
  LCD  : "LCDRoutines4"  'for the LCD methods
  UTIL : "Utilities"     'for general methods

PUB Go                  
  dira [output_pin]~~           'sets pin to an output line with ~~ notation
  outa [output_pin]~~           'makes the pin high   
  LCD.INITIALIZE_LCD            'initialize the LCD
  repeat                        'repeat forever, no number after repeat
     PotValue:=UTIL.read3202_0  'reads the potentiometer
     DIV:=1+PotValue/64         'adding 1 keeps value from going to zero                     
     turnOff_LED                'method call
     wait                       'method call
     turnOn_LED                 'method call
     wait                       'method call  
     LCD.POSITION (1,1)            'Go to 1st line 1st space
     LCD.PRINT(STRING("Pot=" ))    'dividing value
     LCD.PRINT_DEC(PotValue)       'print value 
     LCD.SPACE(2)                  'erase over old data 
     LCD.POSITION (2,1)            'Go to 2nd line 1st space
     LCD.PRINT(STRING("Div=" ))    'dividing value
     LCD.PRINT_DEC(div)            'print value
     LCD.SPACE(2)                  'erase over old data  
    
PRI turnOn_LED                   'method to set the LED line high
    outa[output_pin] :=inv_high  'line that actually sets the LED high
         
PRI turnOff_LED                  'method to set the LED line low
    outa[output_pin] :=inv_low   'line that actually sets the LED low

PRI wait                         'delay method
    waitCnt(clkfreq/div + cnt)   'delay is specified by the div





{{11 Sep 09     Harprit Sandhu
Segment
Propeller Tool Ver 1.2.6
Chapter 17  Program 1
}}

PUB segment                    
   dira[output]~~                     'output pin
  repeat                             'loop   
      !OUTA[output]                  'toggle output line
      waitcnt(11_364 +cnt)           'wait for the A4 freq






{{12 Sep 09    Harprit Sandhu
Play8Notes.spin
Propeller Tool Ver. 1.2.6
Chapter 17  Program 02

This program plays 8 notes, bare bones

Define the constants we will use
}}

CON      
  _CLKMODE=XTAL1 + PLL2X            'The system clock spec
  _XINFREQ  = 5_000_000              'the crystal frequency
  repfactor =500                     'number of times repeated
  delayfact =1_000_000               'delay between notes
  output    = 25
 
PUB Go
dira[output]~~                       'output pin
  repeat                             'outer loop
    repeat repfactor                   
      !OUTA[output]                  'toggle output line
      waitcnt(13_636 +cnt)           'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait 
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(12_170 +cnt)           'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait    
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(11470 +cnt)            'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait 
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(10221 +cnt)            'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(9104 +cnt)             'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait   
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(8595 +cnt)             'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(7639 +cnt)             'wait to synthesize freq 
    waitcnt(delayfact+cnt)           'wait 
    repeat repfactor   
      !OUTA[output]                  'toggle output line
      waitcnt(6818 +cnt)             'wait to synthesize freq
    waitcnt(delayfact+cnt)           'wait







{{ Aug 31 09      Harprit Sandhu
FreqGen8.Spin  
Propeller Tool Ver. 1.2.6
Chapter 17 Program 3
             
This program generates 8 frequencies starting at 440 cycles/sec.
Depends on the position of Pot 1

}}
CON                                                                     
  _CLKMODE=XTAL1+ PLL2X      'The system clock spec
  _XINFREQ = 5_000_000       'Crystal freq
  Output     = 26            'output line for the speaker
  Repfactor  = 100           'number of times to toggle line
 
VAR
{RAM assignment for cogs}                                           
  long  Stack1[50]       'this RAM will be assigned to COG1
  long  Stack2[50]       'this RAM will be assigned to COG2

{variables used for reading pot}
  word  PotValue         'value of the pot reading 
  long  NoteFreq         'actual frequency of the note
  long  NoteDelay        'delay in cycles
 
{variables used in displaying LCD in Cog2}
  'none           

{variables used in GetTone}
  Byte  toneNumber
 
OBJ                             'The Objects we will need for our calls
  LCD  : "LCDRoutines4"         'for controlling the LCD
  UTIL : "Utilities"            'for general methods

DAT
  Tone word 440, 494, 523, 587, 659, 698, 784, 880
 
PUB GO                          'The main method in this program
                                'the potentiometer is read in this cog
  cognew (COG_LCD,   @Stack1)   'create COG_TWO for LCD display                                       
  cognew (COG_PLAY,  @Stack2)   'create COG_THREE for toggling output
  repeat                        'start repeat loop
    PotValue:=UTIL.Read3202_0       'get potValue from the utilities
    ToneNumber:=Potvalue/512 +1     'This reduces the value to 0-15  
  
PRI COG_LCD                        'Handles display  to the LCD                                                                                                                                                                                                                       
  LCD.INITIALIZE_LCD               'set up the LCD              
  REPEAT                           'repeat write to the LCD                   
     LCD.POSITION (1,1)            'Go to 1st line 1st space
     LCD.PRINT(STRING("PotPos =")) 'Potentiometer position
     LCD.PRINT_DEC(ToneNumber)     'print the tune number     
     LCD.SPACE(2)                  'erase over overflows
     LCD.POSITION (2,1)            'Go to 2nd line 1st space
     LCD.PRINT(STRING("FreqOut=")) 'frequency label printed
     LCD.PRINT_DEC(NoteFreq)       'print note cps     
     LCD.SPACE(2)                  'erase over overflows
                                                        
PRI COG_PLAY                       'output for speaker   
  dira[Output]~~                   'output pin
  repeat                           'outer loop
    repeat RepFactor               'inner loop and repeat #
      GetTone                      'gets value for NoteFre 
      !OUTA[output]                'toggle output line
      NoteDelay:=12_000_000/(NoteFreq*2)   'calculate the delay
      waitcnt(NoteDelay +cnt)       'wait for delay to synthesize freq
    waitcnt(clkfreq/2+cnt)

                              
PUB GetTone                       'gets the frequency to be played
  NoteFreq := Tone[toneNumber-1]  'looks up position in DAT statements






{{05 Oct 09     Harprit Sandhu
FreqCounter.Spin
Propeller Tool Ver 1.2.6
Chapter 17 Prog 04
              
The program reads the frequency of a signal on the Input
line and displays it on the LCD. The signal is read as the
number of waves in 1 second. Controlled by Pot 1

Four Cogs are used
        
COG GO reads the frequency
COG COG_LCD displays values on LCD
COG FREQ_GEN generates the frequency
COG COG_OUT generates the 5 freq

}}
CON                                                            
  _CLKMODE=XTAL1+ PLL2X  'The system clock spec
  _XINFREQ = 5_000_000   'crystal                              
  freq5    =25           '5X freq line
  input    =26           'line for input for what is to be read
  output   =27           'line for output of what is generated 
 
VAR                       'these are the variables
  long  Stack[50]         'For CogOne
  long  Stack1[50]        'For freq_gen
  long  Stack2[50]        'For freq_out     
  long  Freq              'read frequency
  long  startTMR
  long  StopTMR
  long  elapsed
  long  pot
 
OBJ                           'These are the methods we will need
  LCD  : "LCDRoutines4"       'for controlling the LCD
  UTIL : "Utilities"          'for general methods

PUB GO                        'This the main method in this program
  Cognew (COG_LCD, @Stack)    'create Cog_TWO
  Cognew (FREQ_GEN, @Stack1)  'create freq generator
  Cognew (COG_OUT, @Stack2)   'create freq out
  dira[input]~   
  repeat
    repeat
    while ina[input]==0        'hold at low
    startTMR:=cnt              'start timer
    repeat     
    while ina[input]==1        'hold at high
    repeat
    while ina[input]==0        'hold at low
    stopTMR:=cnt               'read timer
    elapsed:=stopTMR-startTMR
    freq:=10_000_000/elapsed
    pot:=util.read3202_0        'read Pot 1
    
PRI COG_LCD                     'This is the display, the LCD                                                                                                                                                                                                                       
  LCD.INITIALIZE_LCD            'initialize up the LCD                                     
  REPEAT                        'Routine to write to the LCD                  
     LCD.POSITION (1,1)         '
     LCD.PRINT(STRING("FRQ="))  'Frequency
     LCD.PRINT_DEC(Freq)        'print freq     
     LCD.SPACE(2)               'erase old data                     
     LCD.POSITION (2,1)         '
     LCD.PRINT(STRING("POT="))  'Frequency
     LCD.PRINT_DEC(Pot)         'print Pot reading     
     LCD.SPACE(2)               'erase old data

PRI FREQ_GEN                    'Freq generation based on pot reading
dira[output]~~                  'set output line
   pot:=1000                    'arbitrary non zero value
   repeat                       'loop
     outa[output]~~             'make line high
     waitcnt(clkfreq/pot+cnt)   'wait based on pot        
     outa[output]~              'make line low
     waitcnt(clkfreq/pot+cnt)   'wait based on pot

PRI COG_OUT                        'output signal generation.
  dira[freq5]~~                    'Set pin direction as output
  freq:=1000                       'arbitrary non zero value
  repeat                           'loop           
    outa[freq5]~~                  'make line high
    waitcnt(clkfreq/freq/5+cnt)    'wait 1/5 time for 5X freq
    outa[freq5]~                   'Make line low
    waitcnt(clkfreq/freq/5+cnt)    'wait 1/5 time for 5X freq
    




{{13 Sep 09    Harprit Sandhu  
MemsicWidth.spin
Propeller Tool Ver 1.2.6
Chapter 18 Prog 01

This program measures the pulse width and wave length output
from a Memsic 2125 gravity sensor as it is tilted from
the horizontal plane to the vertical plane

COG_LCD manages the LCD output
COG_0 measures the pulse
                                                                                                      
}}
CON                                                                    
  _CLKMODE=XTAL1+ PLL2X      'The system clock spec
  _XINFREQ = 5_000_000       'crystal frequency
  xaxis  = 25                 '
  output = 26
VAR                                                     
  long  Stack[55]              'FOR LCD COG
  long  Stack1[55]             'FOR OUTPUT COG
  long  startWave              '                                                 
  long  endPulse               '
  long  endWave                '       
  long  PulseLen               '
  long  waveLen                '
  long  frequency
          
OBJ                            'These are the Objects we will need
  LCD  : "LCDRoutines4"        'for controlling the LCD
  UTIL : "Utilities"           'for general methods collection
    
PUB go                           'Cog_0
  cognew (COG_LCD, @Stack)       'starting up Cog LCD 
  cognew (COG_OUT, @Stack1)      'starting up Cog OUT
  DIRA[25]~                      'Make pin input
  repeat                         'Set up the control loop 
    repeat while ina[xaxis]==1       'wait for line 1 to go low. See Manual         
    repeat while ina[xaxis]==0       'wait for line 1 to go low. See Manual 
                                     'the above 2 lines make sure that we see
                                     'aa full wave when we start measuring
    repeat while ina[xaxis]==1       'wait for line 1 to go low. See Manual   
    startWave:=CNT                   'read the timer count

    repeat while ina[xaxis]==0       'wait for line 1 to go low. See Manual
    endPulse:=CNT                    'read the timer count for second time
     
    repeat while ina[xaxis]==1       'wait for line 1 to go low. See Manual.
    endWave:=cnt
   
    PulseLen:=endPulse-startWave     'figure the pulse
    waveLen:=endWave-startWave       'figure the wave Len
    frequency:=10_000_000/waveLen    'figure the freq
    waitcnt(clkfreq/25+cnt)
    
PRI COG_LCD                      'This is running in the new cog                                                                                                                                                                                                                                          
  LCD.INITIALIZE_LCD             'set up the LCD u                                    
  repeat                         'Print to LCD routine
    LCD.POSITION (1,1)           'Position LCD cursor
    LCD.PRINT(String("PL="))     'Pulse
'    LCD.PRINT_DEC((startWave))  'print value
'    LCD.SPACE(2)                'write over old data
    LCD.PRINT_DEC((pulselen))    'print data               
    LCD.SPACE(2)                 'write over old data
    LCD.POSITION (2,1)           'Position LCD cursor
    LCD.PRINT(String("WL="))     'Wave Length
    LCD.PRINT_DEC((wavelen))     'print value
    LCD.SPACE(2)                 'write over old data
    LCD.POSITION (2,11)          'Position LCD cursor
    LCD.PRINT(String("FR="))     'Frequency
    LCD.PRINT_DEC((frequency))   'print value
    LCD.SPACE(4)                 'write over old data

PRI COG_OUT                      'output signal generation.
  dira[output]~~                 'Set pin direction as output
  repeat                         'loop           
    outa[output]~~               'make line high
    waitcnt(pulselen/10+cnt)     'Create hi part of wave
    outa[output]~                'Make line low
    waitcnt(100_000-pulselen+cnt)'Create rest of wave

   



{Chapter 18  Program 2  }


PRI COG_OUT                         'output signal generation.
  dira[output]~~                    'Set pin direction as output
  repeat                            'loop           
    outa[output]~~                  'make line high
    waitcnt(pulselen/5+cnt)         'Create hi part of wave
    outa[output]~                   'Make line low
    waitcnt(200_000-pulselen+cnt)   'Create rest of wave





{{05 Oct 09     Harprit Sandhu
FreqCounter.Spin
Propeller Tool Ver 1.2.6
Chapter 18 Program 3
              
The program reads the frequency of a signal on the Input
line and displays it on the LCD. The signal is read as the
number of waves in 1 second. Controlled by Pot 1

Four Cogs are used
        
COG GO reads the frequency
COG COG_LCD displays values on LCD
COG FREQ_GEN generates the frequency
COG COG_OUT generates the 5 freq

}}
CON                                                            
  _CLKMODE=XTAL1+ PLL2X  'The system clock spec
  _XINFREQ = 5_000_000   'crystal                              
  freq5    =25           '5X freq line
  input    =26           'line for input for what is to be read
  output   =27           'line for output of what is generated 
 
VAR                       'these are the variables
  long  Stack[50]         'For CogOne
  long  Stack1[50]        'For freq_gen
  long  Stack2[50]        'For freq_out     
  long  Freq              'read frequency
  long  startTMR
  long  StopTMR
  long  elapsed
  long  pot
 
OBJ                           'These are the methods we will need
  LCD  : "LCDRoutines4"       'for controlling the LCD
  UTIL : "Utilities"          'for general methods

PUB GO                        'This the main method in this program
  Cognew (COG_LCD, @Stack)    'create Cog_TWO
  Cognew (FREQ_GEN, @Stack1)  'create freq generator
  Cognew (COG_OUT, @Stack2)   'create freq out
  dira[input]~   
  repeat
    repeat
    while ina[input]==0        'hold at low
    startTMR:=cnt              'start timer
    repeat     
    while ina[input]==1        'hold at high
    repeat
    while ina[input]==0        'hold at low
    stopTMR:=cnt               'read timer
    elapsed:=stopTMR-startTMR
    freq:=10_000_000/elapsed
    pot:=util.read3202_0        'read Pot 1
    
PRI COG_LCD                     'This is the display, the LCD                                                                                                                                                                                                                       
  LCD.INITIALIZE_LCD            'initialize up the LCD                                     
  REPEAT                        'Routine to write to the LCD                  
     LCD.POSITION (1,1)         '
     LCD.PRINT(STRING("FRQ="))  'Frequency
     LCD.PRINT_DEC(Freq)        'print freq     
     LCD.SPACE(2)               'erase old data                     
     LCD.POSITION (2,1)         '
     LCD.PRINT(STRING("POT="))  'Frequency
     LCD.PRINT_DEC(Pot)         'print Pot reading     
     LCD.SPACE(2)               'erase old data

PRI FREQ_GEN                    'Freq generation based on pot reading
dira[output]~~                  'set output line
   pot:=1000                    'arbitrary non zero value
   repeat                       'loop
     outa[output]~~             'make line high
     waitcnt(clkfreq/pot+cnt)   'wait based on pot        
     outa[output]~              'make line low
     waitcnt(clkfreq/pot+cnt)   'wait based on pot

PRI COG_OUT                        'output signal generation.
  dira[freq5]~~                    'Set pin direction as output
  freq:=1000                       'arbitrary non zero value
  repeat                           'loop           
    outa[freq5]~~                  'make line high
    waitcnt(clkfreq/freq/5+cnt)    'wait 1/5 time for 5X freq
    outa[freq5]~                   'Make line low
    waitcnt(clkfreq/freq/5+cnt)    'wait 1/5 time for 5X freq


{{28 Sep 09  Harprit Sandhu
7SegDisplay.spin 7SegDisplay.spin
Propeller Tool Ver 1.2.6
Chapter 19 Program 1

Program controls the segments on one 7 segment display
Pot is used to change the delay time
Place Segment Display on perf board as sown in Pictures.
  
}}
CON    
  _CLKMODE=XTAL1+ PLL2X       'The system clock spec
  _XINFREQ     =5_000_000     '10 MHz
 
VAR                      'these are the variables we will use. 
  long stack1[35]        'space for 7 Seg driver
  word delay             'duration for each number
  byte index             'numbering index
 
OBJ                      'These are the methods we will need
  UTIL : "Utilities"     'for general methods
  
PUB Go                          'main cog       
  cognew(SevSeg,@Stack1)   'start new cog for segs
  repeat                        'this main cog's main loop
    delay:=util.getpotval*8  
    
PRI SevSeg                     '
  dira[8..15]~~       
  index:=0
  repeat                      
    index+=1
    'index:=8    'can freeze index at 8 to see all segs on
    case index
        1:                         
          repeat delay   
            outa[8..15]:=%01_111_111     'These numbers build
            outa[8..15]:=%11_111_111     'up the numbers shown
            outa[8..15]:=%11_011_111     'segment at a time
            outa[8..15]:=%11_111_111     'number at a time. 
            outa[8..15]:=%11_111_111     'a ZERO turns a segment on 
            outa[8..15]:=%11_111_111     'in a common anode system 
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_110
        2:                         
          repeat delay  
            outa[8..15]:=%11_111_111    
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_011_111     
            outa[8..15]:=%11_101_111       
            outa[8..15]:=%11_110_111      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_110  
        3:                         
          repeat delay   
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_111_111     
            outa[8..15]:=%11_101_111       
            outa[8..15]:=%11_110_111      
            outa[8..15]:=%11_111_011      
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_110
        4:                         
          repeat delay  
            outa[8..15]:=%01_111_111      
            outa[8..15]:=%11_111_111     
            outa[8..15]:=%11_101_111     
            outa[8..15]:=%11_110_111       
            outa[8..15]:=%11_111_011      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_110  
        5:                         
          repeat delay   
            outa[8..15]:=%01_111_111      
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_110_111     
            outa[8..15]:=%11_111_011       
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_110
        6:                         
          repeat delay  
            outa[8..15]:=%01_111_111    
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_110_111     
            outa[8..15]:=%11_011_111       
            outa[8..15]:=%11_111_011      
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111  
        7:                         
          repeat delay   
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_101_111     
            outa[8..15]:=%11_111_011       
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111
        8:                         
          repeat delay  
            outa[8..15]:=%01_111_111      
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_011_111     
            outa[8..15]:=%11_101_111       
            outa[8..15]:=%11_110_111      
            outa[8..15]:=%11_111_011      
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_111  
        9:                         
          repeat delay   
            outa[8..15]:=%01_111_111      
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_101_111     
            outa[8..15]:=%11_110_111       
            outa[8..15]:=%11_111_011      
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_111
        10:                         
          repeat delay  
            outa[8..15]:=%01_111_111      
            outa[8..15]:=%10_111_111     
            outa[8..15]:=%11_011_111     
            outa[8..15]:=%11_101_111       
            outa[8..15]:=%11_111_111      
            outa[8..15]:=%11_111_011      
            outa[8..15]:=%11_111_101      
            outa[8..15]:=%11_111_111
        11:    
          repeat delay*20   'blanks display for a while  
            outa[8..15]:=%11_111_111 
  
    if index>11      'index reset value
      index:=0


            

{{29 Sep 09   Harprit Sandhu
Metronom1.Spin 
Propeller Tool Ver 1.2.6
Chapter 20 Prog 1

Creating pulses
An electronic metronome. 
Standard is 40 to 208 BPM (beats per minute)
                                           
4 Cogs are used
Cog0 GO, toggles power line once a sec
Cog1 LCD, displays values on LCD
Cog2 Counts, toggles the speaker
Cog3 Calc, calculates the beats

}}
CON                            
  _CLKMODE=XTAL1+ PLL2X    'The system clock spec
  _XINFREQ   = 5_000_000   'crystal rate
                  
  Clickline    = 25      'Clicks speaker
  LED2Line     = 26      'Toggles the 2nd LED
  ledLine      = 27      'the ON led, 1 sec cycle
 
VAR                      'these are the variables we use.
  long  Stack [40]       'for lcd
  long  Stack2[40]       'for counts 
  long  Stack3[40]       'for spkr   
  long  Stack4[40]       'for click
  long  Pot              'for potentiometer reading
  long  bpm              'beats per minute
   
OBJ                          'These are the methods we need
  LCD  : "LCDRoutines4"      'for controlling the LCD
  UTIL : "Utilities"         'for general methods, read potentiomter
                                
PUB GO                            'This the main method in this program
  cognew (lcd_COG,  @Stack)       'create COG for LCD
  cognew (Counts_COG, @Stack2)    'create COG for speaker
  cognew (Calc_COG, @Stack3)      'create COG for calculations
  dira[ledLine]~~                 'Power indicator
  repeat                          'The main cog blinks an LED only                                  
    outa[ledLine]~                'These lines just blink an LED
    waitcnt(clkfreq/2+cnt)        'as an ON indicator as a one
    outa[ledLine]~~               'second reference
    waitcnt(clkfreq/2+cnt)        'line 27
 
PRI lcd_COG                       'This is the display to the LCD                                                                                                                                                                                                                       
  LCD.INITIALIZE_LCD              'set up the LCD                                     
  REPEAT                          'Routine to write to the LCD                  
    LCD.POSITION (1,1)            'Position cursor
    LCD.PRINT(STRING("POT VAL="))    'identify signal
    LCD.PRINT_DEC(pot)            'print the Pot reading  
    LCD.SPACE(4)                  'write over old data
    LCD.POSITION (2,1)            'Position cursor
    LCD.PRINT(STRING("BEATS/M="))    'Identify signal
    LCD.PRINT_DEC(bpm)            'print the beats/min                    
    LCD.SPACE(4)                  'write over old data  
                                  '
PRI Counts_COG                    'This COG Toggles the speaker
  dira[LED2Line]~~                '26
  bpm:=60                         'this initializes the value                  
  repeat                          'repeat loop                                  
    outa[LED2Line]~~              'toggle second LED
    waitcnt(clkfreq/(bpm/30)+cnt) 'wait time
    Click_Speaker                 'calls method for this
    outa[LED2Line]~               'turn it off       
    waitcnt(clkfreq/(bpm/30)+cnt) 'wait time
   
PRI Calc_COG                      'This COG calculates the beats
  pot:=10                         'this initializes the value
  bpm:=60                         'this initializes the value
  repeat                          'repeat loop                     
    pot:=util.Read3202_0          'read the potentiometer
    bpm:=40+(10*pot)*(208-40)/40950    'calculate beats from pot reading

PRI Click_speaker                  'makes the click sound
  dira[Clickline]~~                'line 25
  outa[Clickline]~~                'turn on
  outa[Clickline]~                 'turn off               





{{Chapter 21 Program 01
}}

PRI INITIALIZE_LCD                  'The addresses and data used here are
  waitcnt(150_000+cnt)              'specified in the Hitachi data sheet for the
                                    'display. YOU MUST CHECK THE DATA SHEET.
  OUTA[RegSelect] := 0              'three lines are specified so we can write
  OUTA[ReadWrite] := 0              'the initial set up bits for the LCD
  OUTA[Enable]    := 0              'See Hitachi HD44780 data sheet
                                    '                                     
  SEND_INSTRUCTION (%0011_1000)     'Sets DL=8 bits, N=2 lines, F=5x7 font
  waitcnt(50_000+cnt)              'wait for instruction to execute
  SEND_INSTRUCTION (%0000_1111)     'Display on, Cursor on, Blink on 
  waitcnt(12_000+cnt)               'wait for instruction to execute                          
  SEND_INSTRUCTION (%0000_0110)     'Move Cursor, Do not shift display
  waitcnt(12_000+cnt)               'wait for instruction to execute
          




{{Chapter 21 Program 02
}}

PUB CLEAR                            'Clear the LCD display and go home
  SEND_INSTRUCTION (%0000_0001)      'to the 1,1 position




{{Chapter 21 Program 03
}}

PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION   
        'Position the cursor at location
        'HOR_POSITION : Horizontal Position : 1 to 16
        'LINE_NUMBER : Line Number : 1 or 2
CHAR_LOCATION := (HOR_POSITION-1) * 64   'figure location
CHAR_LOCATION += (LINE_NUMBER-1) + 128   'figure location
SEND_INSTRUCTION (CHAR_LOCATION)         'send the instruction to position cursor





{{Chapter 21 Program 04
}}

PRI CHECK_BUSY | BUSY_BIT                     'routine to check busy bit
  OUTA[ReadWrite] := 1                        'Set to read the busy bit        
  OUTA[RegSelect] := 0                        'Set to read the busy bit
  DIRA[DataBit7..DataBit0] := %0000_0000      'Set the entire port to be an input        
  REPEAT                                      'Keep doing it till clear
    OUTA[Enable]  := 1              'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]       'the busy bit is bit 7 of the byte read
    OUTA[Enable]  := 0              'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)                    'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit0] := %1111_1111   'done, set the data port back to output





{{Chapter 21 Program 05
}}

PRI SEND_CHAR (DISPLAY_DATA)                  'set up for writing to the display   
  CHECK_BUSY                          'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0                        'Set up to read busy bit
  OUTA[RegSelect] := 1                        'Set up to read busy bit
  OUTA[Enable]    := 1                        'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to SEND data in
  OUTA[Enable]    := 0                        'Toggle the bit H>L





{{Chapter 21 Program 06
}}

PRI SEND_INSTRUCTION (DISPLAY_DATA)     'set up for writing instructions
  CHECK_BUSY                            'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0                  'Set up to read busy bit        
  OUTA[RegSelect] := 0                  'Set up to read busy bit        
  OUTA[Enable]    := 1                        'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to READ data in
  OUTA[Enable]    := 0                        'Toggle the bit H>L





{{11 Sep 09     Harprit Sandhu
LCDminimal.spin
Propeller Tool Ver 1.2.6

PROGRAM TO BEGIN USING THE LCD

A minimal LCD implementation to allow us to use the LCD in our
experiments immediately.

This program is an absolutely minimal implementation to 
make the LCD usable. You can work on improving it.
                                                                                                                           
                                                        +------------+                         
Schematic                                               +--------+                          
                                                        +----+                          
                                                                                     
POWER ETC:          +----------------------------------------+                            
BASIC CONNECTIONS   1 0 9 8 7 6 5 43 X X G3 2 1 0 9 8 7 6                            
FOR THE EDUCATION                                                                     
KIT ARE STANDARD        PROPELLER               CHIP                                  
CONNECTIONS AND ARE 0 1 2 3 4 5 6 7G B R 38 9 0 1 2 3 4 5                            
NOT SHOWN HERE      +----------------------------------------+                            
                                                                           
                                        +-----+-+-+-+-+-+-+-+----+-+-+                         
                                        +---+-+-+-+-+-+-+-+----+-+                           
                                  5VDC  +-+-+-+-+-+-+-+-+----+                             
                                    ?                                     
                                                                         
                                                                         
                       +----------?-+-+                                   
                                                                   
                            +-------------------------------------------------+               
                                G 5 G S W E 0 1 2 3 4 5 6 7                                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                              +-++-++-++-++-++-++-++-++-++-++-++-++-++-++-+                 
                            +-------------------------------------------------+               
                             16 CHAR BY 2 LINE LCD DISPLAY                                    
                       ? GND  8 BIT MODE                   

Revisons



}}
     
CON
{{
Pin assignment are assigned as constants because the pins are fixed.
These numbers reflect the actual wiring on the board between the Propeller
and the 16x2 LCD display. If you want the LCD on other lines, that would
have to be specified here.  We are going to use 8 bit mode to transfer data
All these numbers refer to lines on the Propeller
}}
       
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the oscillator frequency

  RegSelect     = 16                
  ReadWrite     = 17                 
  Enable        = 18   
  DataBit0      = 8    
  DataBit7      = 15
  waitPeriod    =500_000                      'set the wait period in Milliseconds
  high          =1                        'define the High state
  low           =0                        'define the Low state
{{
Defining high and low states will allow us to invert these when we use
buffers to amplify the output from the prop chip.  We will then make
low=1 and high=0 thus inverting all the values throughout the program 
}}

PUB Go                        
  DIRA[DataBit7..DataBit0]:=%11111111  'the lines for the LCD are outputs
  DIRA[RegSelect] := High         'the lines for the LCD are outputs
  DIRA[ReadWrite] := High         'the lines for the LCD are outputs
  DIRA[Enable]    := High         'the lines for the LCD are outputs

  INITIALIZE_LCD                  'initialize the LCD
  waitcnt(5_000_000+cnt)          'wait for LCD to start up
  CLEAR                           'clear the LCD
  repeat                            'repeat forever
    clear
    repeat 4                        'print 4 'A's
      SEND_CHAR ("A")                                                                                              
    repeat 4                        'print 4 'a's
      SEND_CHAR ("b")                                                                                              
    POSITION (1,2)                  'move to POSITION: line 2, space 1
    repeat 4                        'print 4 'B's
      SEND_CHAR ("C")                                                                                              
    repeat 4                        'print 4 'b's
      SEND_CHAR ("d")
    waitcnt(10_000_000+cnt)
                                                                                                                 
PRI INITIALIZE_LCD                'The addresses and data used here are
  waitcnt(500_000+cnt)          'specified in the Hitachi data sheet for
                                  'display. YOU MUST CHECK THIS FOR YOURSELF
  OUTA[RegSelect] := Low          'these three lines are specified to write
  OUTA[ReadWrite] := Low          'the initial set up bits for the LCD
  OUTA[Enable]    := Low          'See Hitachi HD44780 data sheet
                                  'YOU MUST CHECK THIS FOR YOURSELF.
  SEND_INSTRUCTION (%0011_0000)   'Send 1sr
  waitcnt(49_200+cnt)             'wait                              
  SEND_INSTRUCTION (%0011_0000)   'Send 2nd
  waitcnt(1_200+cnt)              'wait               
  SEND_INSTRUCTION (%0011_0000)   'Send 3rd
  waitcnt(12_000+cnt)             'wait                                                                                                               
  SEND_INSTRUCTION (%0011_1000)   'Sets DL=8 bits, N=2 lines, F=5x7 font
  SEND_INSTRUCTION (%0000_1111)   'Display on, Cursor on, Blink on     
  SEND_INSTRUCTION (%0000_0001)   'clear LCD
  SEND_INSTRUCTION (%0000_0110)   'Move Cursor, Do not shift display
                                                                                                                 
PUB CLEAR                          'Clear the LCD display and go home
  SEND_INSTRUCTION (%0000_0001)                                                                                       
                                                                                                                      
PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION    'Position cursor 
  'HOR_POSITION : Horizontal Position : 1 to 16
  'LINE_NUMBER : Line Number : 1 or 2        
  CHAR_LOCATION := (HOR_POSITION-1) * 64  'figure location
  CHAR_LOCATION += (LINE_NUMBER-1) + 128  'figure location
  SEND_INSTRUCTION (CHAR_LOCATION)   'send the instr to position cursor                                                            
                                                
PUB SEND_CHAR (DISPLAY_DATA)   'set up for writing to the display    
  CHECK_BUSY                   'wait for busy bit to clear before sending
  OUTA[ReadWrite] := Low       'Set up to read busy bit
  OUTA[RegSelect] := High      'Set up to read busy bit
  OUTA[Enable]    := High      'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to SEND data in
  OUTA[Enable]    := Low       'Toggle the bit H>L
 
PUB CHECK_BUSY | BUSY_BIT      'routine to check busy bit
  OUTA[ReadWrite] := High      'Set to read the busy bit         
  OUTA[RegSelect] := Low        'Set to read the busy bit
  DIRA[DataBit7..DataBit0] := %0000_0000  'Set the entire port to be an input         
  REPEAT                        'Keep doing it till clear
    OUTA[Enable]  := High       'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]   'the busy bit is bit 7 of the byte read
    OUTA[Enable]  := Low        'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)         'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit0] := %1111_1111  'set the data port back to outputs
                                           
PUB SEND_INSTRUCTION (DISPLAY_DATA) 'set up for writing instructions
  CHECK_BUSY                   'wait for busy bit to clear before sending
  OUTA[ReadWrite] := Low       'Set up to read busy bit         
  OUTA[RegSelect] := Low       'Set up to read busy bit         
  OUTA[Enable]    := High      'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to READ data in 
  OUTA[Enable]    := Low        'Toggle the bit H>L





{{11 Sep 09     Harprit Sandhu
LCDminimal2.spin
Propeller Tool Ver 1.2.6
Chapter 21 Program 8

LCD control.  Comprehensive.

Here are the improvement to program
   Can now send DECIMAL values to the LCD
   Can now send HEX     values to the LCD
   Can now send BINARY  values to the LCD
   Delays in the print routines have been eliminate to speed things up
   The output blinks "Hello world" and 1234567890on the two lines
}}     
CON                          
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the oscillator frequency  
  DataBit0   =  8        'Data uses 8 bits from
  DataBit7   = 15        'lines 8 to 15                 
  RegSelect  = 16        'The three control lines, register select         
  ReadWrite  = 17        'Read Write and
  Enable     = 18        'Enable  line
  waitPeriod =5_000_000  'set the wait period, about 1/2 sec
  high       =1          'define the High state
  low        =0          'define the Low state

VAR
  long index             'used to count the chars in the string
  long char_index        'used to count the chars in the string
                              
PUB START
   DIRA[16..18]~~                          'set these 8 lines to outputs
  INITIALIZE_LCD                           'this METHOD initializes on the LCD
  DIRA[DataBit7..DataBit0] := %1111_1111   '11 lines control the LCD as outputs         
  DIRA[RegSelect] := 1                         'select the register for the LCD
  DIRA[ReadWrite] := 1                         'set to write
  DIRA[Enable]    := 1                         'enable operation
  repeat                                       'this loops forever
    initialize_lcd                             'init the LCD
    waitCnt(waitPeriod + cnt)                  'wait to see it clear
    position (1,1)                             ' go to pos 1,1
    PRINT(string("Hello world"))               'display text message
    POSITION (2, 1)                            'pos to line 2 position 1
    PRINT_DEC (1234567890)                     'print the number  
    waitCnt(waitPeriod + cnt)                  'wait a while before looping
                                                                                                                                                                                                                                                                               
PRI INITIALIZE_LCD                    'The addresses and data used here are
  waitcnt(500_000+cnt)                'specified in the Hitachi data sheet for the
                                      'display. YOU MUST CHECK THIS FOR YOURSELF.
  OUTA[RegSelect] := 0                'three lines are specified so we can write
  OUTA[ReadWrite] := 0                'the initial set up bits for the LCD
  OUTA[Enable]    := 0                'See Hitachi HD44780 data sheet                                   
  SEND_INSTRUCTION (%0011_1000)       'Sets DL=8 bits, N=2 lines, F=5x7 font
  SEND_INSTRUCTION (%0000_0001)           'clears the LCD
  SEND_INSTRUCTION (%0000_1100)           'Display on, Cursor off, Blink off                                           
  SEND_INSTRUCTION (%0000_0110)           'Move Cursor, Do not shift display
  {this blank line ends this method}
   
PRI CLEAR                           'Clear the LCD display and go home
  SEND_INSTRUCTION (%0000_0001)     'This is the clear screen and go home command
  {this blank line ends this method}
                                            
PRI PRINT (the_line)               'routine handles more Chars at a time
                                   'called as PRINT(string("the_line"))
                                   'the line" contains the pointer to the line. 
                                   'because we have to point to the line         
                                   'zero terminated but we will not use that. 
                                   'We will use the string size instead.
                                   'This was is easier to understand
  index:=0                         'Reset the counter to count chars sent
  repeat                           'repeat for all chars in the list
    char_index:= byte[the_line][index++]   'char_index contains the char/byte
                                           'pointed to by the index
    SEND_CHAR (char_index)                 'send the 'pointed to' char to the LCD
  while index<strsize(the_line)            'keep doing it till last char is sent

PRI POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION    'Position the cursor
                                                           'at location
  CHAR_LOCATION := (LINE_NUMBER-1) * 64   'fig loc. See Hitachi HD44780 data sht
  CHAR_LOCATION += (HOR_POSITION-1) + 128 'fig loc. See Hitachi HD44780 data sht
  SEND_INSTRUCTION (CHAR_LOCATION)        'send the instruction to position cursor
                                       
PRI SEND_CHAR (DISPLAY_CHAR)            'set up for writing to the display   
  CHECK_BUSY                            'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0                        'Set up to read busy bit
  OUTA[RegSelect] := 1                        'Set up to read busy bit
  OUTA[Enable]    := 1                        'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_CHAR    'Ready to SEND data in
  OUTA[Enable]    := 0                        'Toggle the bit H>L 

PRI CHECK_BUSY | BUSY_BIT                     'routine to check busy bit
  OUTA[ReadWrite] := 1                        'Set to read the busy bit        
  OUTA[RegSelect] := 0                        'Set to read the busy bit
  DIRA[DataBit7..DataBit0] := %0000_0000      'Set the entire port to be an input        
  REPEAT                                      'Keep doing it till clear
    OUTA[Enable]  := 1              'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]       'the busy bit is bit 7 of the byte read
                                    'INA is the 32 input pins on the PROP and we
                                    'are reading data bit 7 which is on pin 15!
    OUTA[Enable]  := 0              'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)                   'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit0] := %1111_1111  'done set the data port back to outputs  
                                   
PRI SEND_INSTRUCTION (DISPLAY_DATA)    'set up for writing instructions
  CHECK_BUSY                           'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0                        'Set up to read busy bit        
  OUTA[RegSelect] := 0                        'Set up to read busy bit        
  OUTA[Enable]    := 1                        'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := DISPLAY_DATA    'Ready to READ data in
  OUTA[Enable]    := 0                        'Toggle the bit H>L 

PRI PRINT_DEC (VALUE) | TEST_VALUE      'for printing values in decimal format
  IF (VALUE < 0)                        'if it is a negative value            
    -VALUE                              'change it to a positive
    SEND_CHAR("-")                      'and print a - sign on the LCD
  TEST_VALUE := 1_000_000_000           'we get individual digits by comp to this
                                        'value
  REPEAT 10                             'There are 10 digits maximum
    IF (VALUE => TEST_VALUE)            'see if our num is bigger than testValue
      SEND_CHAR(VALUE / TEST_VALUE + "0")  'if it is divide to get the digit
      VALUE //= TEST_VALUE                 'figure the nxt val for the nxt digit
      RESULT~~                             'result so we can pass it on
    ELSEIF (RESULT OR TEST_VALUE == 1)     'if the result 1 then division was even
      SEND_CHAR("0")                       'so we sent out a zero
    TEST_VALUE /= 10                       'we div by 10 to test the next digit
                                                                                          
PRI PRINT_HEX (VALUE, DIGITS)              'for printing values in HEX format
  VALUE <<= (8 - DIGITS) << 2              'you can specify up to 8 digits or
                                           'FFFFFFFF max
  REPEAT DIGITS                            'do each digit
    SEND_CHAR(LOOKUPZ((VALUE <-= 4) & $F : "0".."9", "A".."F"))
                                       'use look up table to select character
                                             
PRI PRINT_BIN (VALUE, DIGITS)                 'for printing values in BINARY format
  VALUE <<= 32 - DIGITS                       '32 digits is the max for our system
  REPEAT DIGITS                               'Repeat for digits desired
    SEND_CHAR((VALUE <-= 1) & 1 + "0")        'send a 1 or a 0 
  {this blank line ends this method}                                                     





{{ 21 - 09}}  
OBJ
LCD : "LCDRoutines"         'We will be using these METHODS in this program
UTIL : "Utilities"          'We will be using these METHODS in this program





{{21 Sep 09     Harprit Sandhu 
LCDRoutines.spin
Propeller Tool Ver 1.2.6
Chapter 21 Program 10

LCD ROUTINES     

The following are the names of the methods described in this program
  INITIALIZE_LCD
  INITIALIZE_LCD4 not yet working right.
  PRINT (the_line)
  POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION
  SEND_CHAR (DISPLAY_CHAR)
  SEND_CHAR (DISPLAY_CHAR)
  PRINT_DEC (VALUE) | TEST_VALUE
  PRINT_HEX (VALUE, DIGITS)
  PRINT_BIN (VALUE, DIGITS)
  CLEAR
  HOME
  SPACE (QTY)

Revisions
  04 Oct 09  Initialize made more robust, misc unnecessary calls removed.
 
}}
CON                             'all the constants used by all the METHODS
                                'in this program have to be listed here            
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          '10 Mhz                                 
  DataBit0   =  8               'Data uses 8 bits from here on
  DataBit1   =  9
  DataBit2   = 10
  DataBit3   = 11               'All these bits dont need to be named but
  DataBit4   = 12               'are named so that they can be called by
  DataBit5   = 13               'name if the need ever arises
  DataBit6   = 14
  DataBit7   = 15                                
  RegSelect  = 16               'The three control lines          
  ReadWrite  = 17               '           
  Enable     = 18               '
  high       =1                 {define the High state}
  low        =0                 {define the Low state}

VAR                             'these are the variables we will use.
   byte  temp                   'for use as a pointer
   byte  index                  'to count characters

PUB Go
  INITIALIZE_LCD
  repeat          
    print(String("1234567890  L1"))
    position(2,1)
    print(String("On second line"))
    waitcnt(3_000_000+cnt)
    clear
    waitcnt(3_000_000+cnt)
'================================================================================                                                                                                                                                                                           
{{initialize the LCD to use 8 lines of data
Includes a half second delay, clears the display and positons to 1,1
no variables used
}}
PUB INITIALIZE_LCD                     'The addressses and data used here are
  waitcnt(5_000_000+cnt)               'specified in the Hitachi data sheet
  DIRA[DataBit0..Enable]~~             'YOU MUST CHECK THIS FOR YOURSELF.
  SEND_INSTRUCTION (%0011_0000)        'Send 1
  waitcnt(49_200+cnt)                  'wait                              
  SEND_INSTRUCTION (%0011_0000)        'Send 2
  waitcnt(1_200+cnt)                   'wait               
  SEND_INSTRUCTION (%0011_0000)        'Send 3
  waitcnt(12_000+cnt)                  'wait                 
  SEND_INSTRUCTION (%0011_1000)        'Sets DL=8 bits, N=2 lines, F=5x7 font
  SEND_INSTRUCTION (%0000_1110)        'Display on, Blink on, Sq Cursor off                                           
  SEND_INSTRUCTION (%0000_0110)        'Move Cursor, Do not shift display
  SEND_INSTRUCTION (%0000_0001)        'clears the LCD
  POSITION (1,1)
'================================================================================                                                                                                                                                                                             
{{Sends instructions as opposed to a character to the LCD
no variables are used
}}                                                                      
PUB SEND_INSTRUCTION (D_DATA)    'set up for writing instructions
  CHECK_BUSY                           'wait for busy bit to clear b
  OUTA[ReadWrite] := 0                 'Set up to read busy bit        
  OUTA[RegSelect] := 0                 'Set up to read busy bit        
  OUTA[Enable]    := 1                 'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := D_DATA   'Ready to READ data in
  OUTA[Enable]    := 0                 'Toggle the bit H>L to xfer the data                              
'================================================================================
{{Sends a character to the LCD
}}
PUB SEND_CHAR (D_CHAR)           'set up for writing to the display   
  CHECK_BUSY                           'wait for busy bit to clear
  OUTA[ReadWrite] := 0                 'Set up to read busy bit
  OUTA[RegSelect] := 1                 'Set up to read busy bit
  OUTA[Enable]    := 1                 'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit0] := D_CHAR    'Ready to SEND data in
  OUTA[Enable]    := 0                 'Toggle the bit H>L
'================================================================================
{{Print a line of characters to the LCD
uses variables index and temp
}}                                                                
PUB PRINT (the_line)              'This routine handles more than one Char
                                  'called as PRINT(string("the_line"))
                                  '"the_line" contains the pointer to line.
                                  'because we have to point to the line
                                  'zero terminated but will not use that.
                                  'use the string size instead. Easier
  index:=0                        'Reset the counter we are using
  repeat                          'repeat for all chars in the list
    temp:= byte[the_line][index++]'temp contains the char pointed by index
    SEND_CHAR (temp)              'send the 'pointed to' char to the LCD
  while index<strsize(the_line)   'keep doing it till the last char is sent
'================================================================================
{{Position cursor
}}
PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION  'Position the cursor
  'Horizontal Position : 1 to 16       'specified by the two numbers
  'Line Number : 1 or 2       
  CHAR_LOCATION := (LINE_NUMBER-1) * 64   'figr loc. See Hitachi HD44780 data
  CHAR_LOCATION += (HOR_POSITION-1) + 128 'figr loc. See Hitachi HD44780 data
  SEND_INSTRUCTION (CHAR_LOCATION)     'send the instruction to position cursor
'================================================================================          
{{Check for busy
}}
PUB CHECK_BUSY | BUSY_BIT        'routine to check busy bit
  OUTA[ReadWrite] := 1           'Set to read the busy bit        
  OUTA[RegSelect] := 0           'Set to read the busy bit
  DIRA[DataBit7..DataBit0] := %0000_0000  'Set the entire port to be an input        
  REPEAT                         'Keep doing it till clear
    OUTA[Enable]  := 1           'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]    'the busybit is bit 7 of the byte read
                                 'INA is the 32 input pins on the PROP and we
                                 'are reading data bit 7 which is on pin 15!
    OUTA[Enable]  := 0           'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)          'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit0] := %1111_1111  'set the data port back to outputs  
'================================================================================
{{Print decimal
}}
PUB PRINT_DEC (VALUE) | TEST_VALUE'for printing values in decimal format
  IF (VALUE < 0)                  'if it is a negative value            
    -VALUE                        'change it to a positive
    SEND_CHAR("-")                'and print a - sign on the LCD
                                  '
  TEST_VALUE := 1_000_000_000     'we get individual digits by comp to this
                                  'value and then div by 10 to get the nxt val
  REPEAT 10                       'There are 10 digits maximum in our system
    IF (VALUE => TEST_VALUE)      'see if our number is bigger than testValue
      SEND_CHAR(VALUE / TEST_VALUE + "0")     'if it is, divide to get the digit
      VALUE //= TEST_VALUE             'figure the next value for the next digit
      RESULT~~                         'result we can pass it on below
    ELSEIF (RESULT OR TEST_VALUE == 1) 'if the result was a 1 then div was even
      SEND_CHAR("0")                 'so we sent out a zero
    TEST_VALUE /= 10                 'we divide by 10 to test for the next digit
                                                    
'================================================================================
{{Print Hex
}}
PUB PRINT_HEX (VALUE, DIGITS)      'for printing values in HEX format
  VALUE <<= (8 - DIGITS) << 2      'you can specify up to 8 digits or FFFFFFFF max
  REPEAT DIGITS                    'do each digit
    SEND_CHAR(LOOKUPZ((VALUE <-= 4) & $F : "0".."9", "A".."F"))
                                    'use lookup table to select character
'================================================================================
{{Print Binary
}}                                              '
PUB PRINT_BIN (VALUE, DIGITS)      'for printing values in BINARY format
  VALUE <<= 32 - DIGITS            '32 binary digits is the max for our system
  REPEAT DIGITS                    'Repeat for each digit desired
    SEND_CHAR((VALUE <-= 1) & 1 + "0") 'send a 1 or a 0
'================================================================================
{{Clear screen
}}   
PUB CLEAR                       'Clear the LCD display and go home
  SEND_INSTRUCTION (%0000_0001) 'This is the clear screen and go home command
'================================================================================
{{Go to position 1,1
}} 
PUB HOME                          'go to position 1,1. 
  SEND_INSTRUCTION (%0000_0011)   'Not cleared
'================================================================================
{{Print spaces
}}
PUB SPACE (qty)                'Prints spaces, for between numbers
  repeat (qty)
    PRINT(STRING(" "))
'================================================================================
{{
}}         





{{11 Oct 09     Harprit Sandhu
LCDTester.Spin
Propeller Tool Ver. 1.2.6
Chapter 21 Program 11
                             
Test program for LCD Routines 
}}

CON                                                                     
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000
  high       =1          'define the High state
  low        =0          'define the Low state

VAR
  byte index             'used as counter for various uses
 
OBJ
  LCD : "LCDRoutines"    'Using their METHODS in this program
  UTIL : "Utilities"     'Using their METHODS in this program
 
PUB Go

LCD.initialize_lcd           
LCD.print (string("Initialized OK"))
LCD.position(2,1)
LCD.print (string("Print test"))
UTIL.pause (1500)

LCD.clear
LCD.position (1,1)
LCD.print (string("this is 1st line"))
UTIL.pause (300)
LCD.position(2,1)
LCD.print (string("ok is on line 2"))   
UTIL.pause (1500) 

LCD.clear
LCD.print (string("Position test")) 
UTIL.pause (1500)
index:=0
repeat 16
  index := index +1
  LCD.clear
  LCD.position (1,index)
  LCD.print (string("X"))  
  UTIL.pause (300)
index:=0
repeat 16
  index := index +1
  LCD.clear
  LCD.position (2,index)
  LCD.print (string("X"))  
  UTIL.pause (300)
LCD.clear
LCD.print (string("End")) 
repeat



        
{{21 Sep 09    Harprit Sandhu
Utilities0.spin
Propeller Tool Ver 1.2.6
Chapter 21 Program 12

Program UTILITIES 
  Flash         flashes a pin once, toggles it slowly
  Pause         pause in milliseconds

  }}
CON
  high          =1
  low           =0
  waitperiod    =100                                        
 
PUB FLASH (color)                    'routine to flash an LED by color                
    outa[color] :=high               'line that actually sets the LED high
    waitCnt(waitPeriod +cnt)         'wait till counter reaches this value
    outa[color] :=low                'line that actually sets the LED low
    waitCnt(waitPeriod +cnt)         'wait till counter reaches this value                                                                                 
                                     '
PUB PAUSE(millisecs)                 'As set up here it is .25 millisceconds
  waitcnt((clkfreq/1000)*millisecs +cnt)      'based on Osc freq




{{21 Sep 09     Harprit Sandhu 
LCDRoutines4.spin
Propeller Tool Version 1.2.6
Chapter 21 Program 13 and Appendix

LCD ROUTINES for a 4 bit data path.     

The following are the names of the methods described in this program

  INITIALIZE_LCD
  PRINT (the_line)
  POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION
  SEND_CHAR (DISPLAY_CHAR)
  SEND_CHAR (DISPLAY_CHAR)
  PRINT_DEC (VALUE) | TEST_VALUE
  PRINT_HEX (VALUE, DIGITS)
  PRINT_BIN (VALUE, DIGITS)
  CLEAR
  HOME
  SPACE (QTY)

Revisions
  04 Oct 09  Initialize made more robust, misc unnecessary calls removed.
 
}}
CON                             'all the constants used by all the METHODS
                                'in this program have to be listed here            
  _CLKMODE=XTAL1 + PLL2X        'The system clock spec. 2 X multiplier
  _XINFREQ   = 5_000_000        'ext crystal is 5 Mhz, so 10 Mhz operation
  DataBit4   = 12               'are named so that they can be called by
  DataBit5   = 13               'name if the need ever arises
  DataBit6   = 14               '
  DataBit7   = 15               '                 
  RegSelect  = 16               'The three control lines          
  ReadWrite  = 17               'The three control lines           
  Enable     = 18               'The three control lines
  high       =1                 'define the High state
  low        =0                 'define the Low state  
  Inv_high   =0                 'define the Inverted High state
  Inv_low    =1                 'define the Inverted Low state

VAR                             'these are the variables we will use
   byte  temp                   'for use as a pointer
   byte  index                  'to count characters

PUB Go
  INITIALIZE_LCD
  repeat          
    print(String("4bit mode line 1"))
    position(2,1)
    print(String("4bit mode line 2"))
    waitcnt(clkfreq/4+cnt)
    clear
    waitcnt(clkfreq/4+cnt)
                                                                                                                                                                                          
{{initialize the LCD to use 4 lines of data
Includes the half second delay, clears the display and positons to 1,1
no variables used
}}
PUB INITIALIZE_LCD                'The addresses and data used here are
  waitcnt(150_000+cnt)            'specified in the Hitachi data sheet for the
  DIRA[DataBit4..Enable]~~        'display. YOU MUST CHECK THIS FOR YOURSELF.
  SEND_INSTRUCTION (%0011)        'Send 1st
  waitcnt(49_200+cnt)             'wait                              
  SEND_INSTRUCTION (%0011)        'Send 2nd
  waitcnt(1_200+cnt)              'wait               
  SEND_INSTRUCTION (%0011)        'Send 3rd
  waitcnt(12_000+cnt)             'wait
  SEND_INSTRUCTION (%0010)        'set for 4 bit mode
  waitcnt(12_000+cnt)             'wait
   
  SEND_INSTRUCTION2 (%0010_1000)  'Sets DL=4 bits, N=2 lines, F=5x7 font
' waitcnt(12_000+cnt)            'wait
  SEND_INSTRUCTION2 (%0000_1110)  'Display on, Blink on, Sq Cursor off
' waitcnt(12_000+cnt)            'wait
  SEND_INSTRUCTION2 (%0000_0110)  'Move Cursor, Do not shift display
' waitcnt(12_000+cnt)            'wait
  SEND_INSTRUCTION2 (%0000_0001)  'clears the LCD
  'waitcnt(12_000+cnt)            'wait 
  POSITION (1,1)
                                                                                                                                                                                             
{{Sends instructions as opposed to a character to the LCD
no variables are used
}}                                                                      
PUB SEND_INSTRUCTION (D_DATA)        'set up for writing instructions
  CHECK_BUSY                         'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0               'Set up to read busy bit        
  OUTA[RegSelect] := 0               'Set up to read busy bit        
  OUTA[Enable]    := 1               'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit4] := D_DATA 'Ready to READ data in
  OUTA[Enable]    := 0               'Toggle the bit H>L to xfer the data                              
                                                                                                                                                                                            
{{Sends an instruction as opposed to a character to the LCD
no variables are used
}}                                                                   
PUB SEND_INSTRUCTION2 (D_DATA)      'set up for writing instructions
  CHECK_BUSY                        'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0              'Set up to read busy bit        
  OUTA[RegSelect] := 0              'Set up to read busy bit        
  OUTA[Enable]    := 1              'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit4] := D_DATA>>4   'Ready to READ data in
  OUTA[Enable]    := 0                 'Toggle the bit H>L to xfer the data   
  OUTA[Enable]    := 1                 'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit4] := D_DATA   'Ready to READ data in
  OUTA[Enable]    := 0                 'Toggle the bit H>L to xfer the data
        
{{Sends a single character to the LCD in two halves
}}
PUB SEND_CHAR (D_CHAR)           'set up for writing to the display   
  CHECK_BUSY                     'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0           'Set up to send data
  OUTA[RegSelect] := 1           'Set up to send data
  OUTA[Enable]    := 1           'go high
  OUTA[DataBit7..DataBit4] := D_CHAR>>4  'Send high 4 bits
  OUTA[Enable]    := 0                 'Toggle the bit H>L
  OUTA[Enable]    := 1                 'go high again
  OUTA[DataBit7..DataBit4] :=D_CHAR    'send low 4 bits
  OUTA[Enable]    := 0                 'Toggle the bit H>L

{{Print a line of characters to the LCD
uses variables index and temp
}}                                                                
PUB PRINT (the_line)       'This routine handles more than one Char at a time
                           'called as PRINT(string("the_line"))  
                           '"the_line" contains the pointer to line. Line is
                           'because we have to point to the line 
                           'zero terminated but we will not use that.  We will
                           'use the string size instead. Easier to understand
  index:=0                 'Reset the counter we are using to count chars sent
  repeat                   'repeat for all chars in the list
    temp:= byte[the_line][index++] 'temp contains the char/byte pointed by index
    SEND_CHAR (temp)               'send the 'pointed to' char to the LCD
  while index<strsize(the_line)    'keep doing it till the last char is sent

{{Position cursor
}}
PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION  'Position the cursor  'Line Number : 1 to 4       
  'Horizontal Position : 1 to 20          'specified by the two numbers
  CHAR_LOCATION := (LINE_NUMBER-1) * 64   'figure location. See Hitachi HD44780
  CHAR_LOCATION += (HOR_POSITION-1) + 128 'figure location. See Hitachi HD44780
' CHAR_LOCATION += (HOR_POSITION-1) + 128
' CHAR_LOCATION += (HOR_POSITION-1) + 128 
  SEND_INSTRUCTION2 (CHAR_LOCATION)       'send the instruction to position cursor
         
{{Check for busy
}}
PUB CHECK_BUSY | BUSY_BIT              'routine to check busy bit
  OUTA[ReadWrite] := 1                 'Set to read the busy bit        
  OUTA[RegSelect] := 0                 'Set to read the busy bit
  DIRA[DataBit7..DataBit4] := %0000    'Set the entire port to be an input        
  REPEAT                          'Keep doing it till clear
    OUTA[Enable]  := 1            'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]     'the busybit is bit 7 of the byte read
                                  'INA is the 32 input pins on the PROP and we
                                  'are reading data bit 7 which is on pin 15!
    OUTA[Enable]  := 0            'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)           'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit4] := %1111 'done, so set the data port back to outputs  

{{Print a decimal value, whole numbers only
}}
PUB PRINT_DEC (VALUE) | TEST_VALUE   'for printing values in decimal format
  IF (VALUE < 0)                  'if it is a negative value            
    -VALUE                        'change it to a positive
    SEND_CHAR("-")                'and print a - sign on the LCD
  TEST_VALUE := 1_000_000_000     'we get individual digits by comparing to this
                                  'value and then dividing by 10 to get next value
  REPEAT 10                       'There are 10 digits maximum in our system
    IF (VALUE => TEST_VALUE)      'see if our number is bigger than testValue
      SEND_CHAR(VALUE / TEST_VALUE + "0")     'if it is, divide to get the digit
      VALUE //= TEST_VALUE        'figure the next value for the next digit
      RESULT~~                    'result of what just did pass it on below
    ELSEIF (RESULT OR TEST_VALUE == 1) 'if the result was a 1 then div was even
      SEND_CHAR("0")               'so we sent out a zero
    TEST_VALUE /= 10               'we divide by 10 to test for the next digit                                                                                      

{{Print a Hexadecimal value
}}
PUB PRINT_HEX (VALUE, DIGITS)     'for printing values in HEX format
  VALUE <<= (8 - DIGITS) << 2     'you can specify up to 8 digits or FFFFFFFF max
  REPEAT DIGITS                   'do each digit
    SEND_CHAR(LOOKUPZ((VALUE <-= 4) & $F : "0".."9", "A".."F"))
                                  'use lookup table to select character

{{Print a Binary value
}}                                              '
PUB PRINT_BIN (VALUE, DIGITS)          'for printing values in BINARY format
  VALUE <<= 32 - DIGITS                '32 binary digits is the max for our sys
  REPEAT DIGITS                        'Repeat for each digit desired
    SEND_CHAR((VALUE <-= 1) & 1 + "0") 'send a 1 or a 0

{{Clear screen
}}   
PUB CLEAR                              'Clear the LCD display and go home
  SEND_INSTRUCTION2 (%0000_0001)       'This is the clear screen and go home command

{{Go to position 1,1   Does not clear the screen
}} 
PUB HOME                               'go to position 1,1. 
  SEND_INSTRUCTION2 (%0000_0011)       'Not cleared

{{Print spaces
}}
PUB SPACE (qty)                        'Prints spaces, for between numbers
  repeat (qty)
    PRINT(STRING(" "))





{{Dec 31 09    Harprit Sandhu

Chapter 24 Program 01

    outa[ServoLine]~
    waitcnt((166,667-(PotValue * 15000 / 4095) + 7500 + cnt)
    outa[ServoLine]~~
    waitcnt((PotValue * 15000 / 4095))+ 7500 + cnt)





{{ 06 Sep 09     Harprit Sandhu 
RC_ServoPosition.spin
Propeller Tool Version 1.2.6
Chapter 24 Program 02
     
READING A SERVO'S POSITION  uses pin 23

This program allows you to tie the signal sent to an
R/C servo to the position that it goes to.

Connections

White  P23 signal from Prop
Red 5 volts
Black ground

}}   
CON                                                                            
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000
   outPin  =23                   'line the servo is on
                                  
VAR                             'these are the variables we will use.
  long ServoPos                 'The program will read this variable from
                                'the main Hub RAM to determine the
                                'servo signal's high pulse duration
  long stack [15]               'space for Cog for LCD
  long stack2[50]               'space for Move Motor Cog
  long pcount                   '
 
OBJ                              'These are the methods we will need for our calls
  LCD  : "LCDRoutines4"          'for the LCD methods
  UTIL : "Utilities"             'for general methods, pot
  
PUB Go                           'main cog
  dira[outPin]~~                     'set direction for amplifier              
  cognew(MoveMotor(outPin),@Stack)   'start a new cog and run the MoveMotor method
                                 'on it and output pulses on Pin 23 
                                 'The new cog that is started above continuously
                                 'reads the "position" variable as it's changed
                                 'by the example Spin code below
  cognew(cog_two, @stack2)       'start new cog for the LCD                         
  repeat                         'this is the Cog's main loop                                                                                                 
    pcount:=UTIL.Read3202_0      'get the pot reading from the utilities
    ServoPos:=7200+pcount*4      'calculate position count

Pub cog_two                         'set up and run the LCD            
  LCD.INITIALIZE_LCD                'initialize the LCD
  repeat                            'LCD loop                
    LCD.POSITION (1,1)              'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot Pos="))   'Potentiometer position ID
    LCD.PRINT_DEC(Pcount)           'print the pot reading                                                               
    LCD.SPACE(2)                    'erase over old text      
                     
PUB MoveMotor(Pin)|LowTime,period   'method to toggle the output line, set
                                    'up first
  dira[Pin]~~                       'Set the direction of "Pin" to be an output
  ctra[30..26]:=%00100              'Set this cog's "A Counter" in single
                                    'ended NCO/PWM mode (where frqa always                                            
                                    'accumulates to phsa and the Apin output
                                    'state is bit 31 of the phsa value)                               
  ctra[5..0]:=Pin                   'Set the "A pin" of this cog's "A Counter"
                                    'to be "Pin"                                          
  frqa:=1                           'Set this counter's frqa value to 1 (so 1
                                    'will be added to phsa on each clock pulse)
  ServoPos:=0                       'Start with position=0 (until the position
                                    'value is changed by another cog)                
  LowTime:=clkfreq/60               'Set the time that the pulse will be low
                                    'to 16ms = 1/60 secs
  period:=cnt                       'Store current value of the system counter
  repeat                            'line toggling routine.
    phsa:=-ServoPos                 'Send a high pulse for "position" number of
                                    'clock cycles. Note negative sign
    period:=period+LowTime          'Calculate what system clock's value will
                                    'be at the end of this cycle's period
    waitcnt(period)                 'Wait for the system counter to reach the
                                    '"period" value (end of cycle)




{{04 Sep 09     Harprit Sandhu  
RunMotorOnly.spin 
Propeller Tool Version 1.2.6
Chapter 25 Program 01 
     
RUNNING A DC MOTOR. ON CONTROL ONLY TO
CONFIRM CONNECTIONS

This program runs the motor if turned on

Lines on Xavien amp as identified in the diagram are
line 1    Brake tie it to ground to turn it off
line 2    PWM signal     line 6 on Prop
line 3    Direction      line 7 on Prop

Connections are
Amplifier brake       P5
Amplifier PWM         P6
Amplifier direction   P7

}}   
CON                                                    
  _CLKMODE=XTAL1+ PLL2X              'The system clock spec
  _XINFREQ = 5_000_000               'crystal             
  BRK = 2
  PWM = BRK + 1
  DIR = PWM + 1
 
PUB Go                               'main Cog
  dira[BRK..DIR]~~                   'set direction for 3 lines              
  outa[BRK..DIR]:=%000               'make the lines low at start
   repeat
     outa[PWM]~~                      'turn on the PWM 100%




{{04 Sep 09  Harprit Sandhu
ReadDisplayPot.spin 
Propeller Tool Version 1.2.6
Chapter 25 program 2 
     
RUNNING A MOTOR, Read Pot/NO SPEED CONTROL

This program runs the motor backward or forward
at full speed based on the potentiometer position.
Reverses at 2048
Pot position is displayed on the LCD
   
Lines on Xavien amp as identified in the diagram are
line 1    Brake tie it to ground to turn it off
line 2    PWM signal     line 6 on Prop
line 3    Direction      line 7 on Prop

Connections are
Amplifier brake       P5
Amplifier PWM         P6
Amplifier direction   P7

}}   
CON                                                               
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000                   '            
   BRK  =  5
   PWM  =  BRK+1
   DIR  =  BRK+2
  
VAR
  long position
  long stack2[50]               'space for Cog two
  long pcount                   'potentiometer reading.
   long  potpos
OBJ                             'These are the methods we will need
  LCD  : "LCDRoutines4"          'for the LCD methods
  UTIL : "Utilities"            'for general methods

PUB Go                          'main Cog
  dira[BRK..DIR]~~              'set direction for lines              
  outa[BRK..DIR]:=%011          'make the lines high, brake off
  Cognew(cog_two, @stack2)      'start new Cog for the LCD                         
  repeat                        'this Cog's main loop                                                                                                 
    pcount:=UTIL.Read3202_0     'get he pot reading from the utilities
    if pcount<2048              'check for center position
      outa[DIR]~                'forward direction set
      pcount:=(2048-pcount)*2   'set center and double the 127 to get near 255
    else                        'or
      outa[DIR]~~               'reverse direction
      pcount:=(pcount-2048)*2   'set center and double the 127 to get near 255
    potpos:=pcount
Pub Cog_two                     'set up and run the LCD            
  LCD.INITIALIZE_LCD            'initialize the LCD
  repeat                        'LCD loop                
    LCD.POSITION (1,1)          'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot position")) 'Potentiometer position ID
    LCD.POSITION (2,1)          'Go to 1st line 1st space
    LCD.PRINT_DEC(Potpos)       'print the pot reading                                                               
    LCD.SPACE(2)                'erase over old data

{{07 Sep 09   Harprit Sandhu
MotorFromPot.spin 
RUNNING A DC MOTOR FROM A POTENTIOMETER
Chapter 25 Program 3

This program allows you to control the speed and the direction
of a motor from a potentiometer

Lines on Xavien amp as identified in the diagram are
line 1    Brake tie it to ground to turn it off
line 2    PWM signal     line 6 on Prop
line 3    Direction      line 7 on Prop

Connections are
Amplifier brake       P5
Amplifier PWM         P6
Amplifier direction   P7   

}}
CON                                                                             
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000          'crystal
                    '            
  BRK  =  5
  PWM  =  BRK+1
  DIR  =  BRK+2
  
  PotMax = 1000          'The maximum power to the motor OUT OF 4095
  PotMin =  40           'The minimum power to the motor OUT OF 4095

VAR                      'these are the variables we will use.
  long PulsWidth         'The assembly program will read this variable from
                         'the main Hub RAM to determine the
                         'servo signal's high pulse duration
  long stack [50]        'space for Cog managing the motor pulses
  long stack2[50]        'space for Cog two
  long pcount            'potentiometer reading.
  byte arrow             'motor direction arrow
 
OBJ                       'These are the methods we need
  LCD  : "LCDRoutines4"   'for the LCD methods
  UTIL : "Utilities"      'for general methods
  
PUB Go                          'main cog
  dira[BRK..DIR]~~              'set direction for amplifier
  outa[BRK..DIR]:=%000
  cognew(MoveMotor(6),@Stack)   'start a new cog and run the MoveMotor method
                                'on it and output pulses on Pin 7 
                                'The new cog that is started above continuously
                                'reads the "position" variable as it's changed
                                'by the example Spin code below
  cognew(cog_two, @stack2)      'start new cog for the LCD   
  repeat                        'this cog's main loop   
    pcount:=UTIL.Read3202_0     'get he pot reading from the utilities
    if pcount<2047              'check for center position
      outa[DIR]~                'forward direction set                        
      arrow:=0                  'direction arrow
      pcount:=(2047-pcount)*2   'set center and double the 127 to get near 255
    else                        'or
       outa[DIR]~~              'reverse direction                           
       arrow:=1                 'direction arrow
       pcount:=(pcount-2047)*2  'set center and double the 127 to get near 255
    if pcount<PotMin            'check Min value
       pcount:=Potmin           'set Min value
    if pcount>PotMax            'check Max value
       pcount:=Potmax           'check Max value
    PulsWidth:=pcount*24        'multiply reading to get 4095
                                '(10000/4096=24)

PUB cog_two                        'set up and run the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop                 
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Pos="))      'Potentiometer position ID
    LCD.PRINT_DEC(pulsWidth/24)    'print the pot reading 
    LCD.SPACE(2)                   'erase over old data   
    LCD.POSITION (1,11)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Dir="))      'Potentiometer position ID
    LCD.PRINT_DEC(arrow)           'print the pot reading 
    LCD.SPACE(2)                   'erase over old data

PUB MoveMotor(Pin)|WaveLength,period  'subroutine to toggle the output line, set
                                   'up first
  dira[Pin]~~                      'Set the direction of "Pin" to be an output
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run in single
                                   'ended NCO/PWM mode (where frqa always 
                                   'accumulates to phsa and the Apin output
                                   'state is bit 31 of the phsa value)  
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog's "A Counter"
                                   'to be "Pin"    
  frqa:=1                          'Set this counter's frqa value to 1 (so 1
                                   'will be added to phsa on each clock pulse)
  PulsWidth:=1000                  'Start with position=0 (until the position
                                   'value is changed by another cog)
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the system counter
  repeat                           'line toggling routine.
    phsa:=-PulsWidth               'Send a high pulse for "position" number of
                                   'clock cycles. NOTE minus sign on PulseWidth.
    period:=period+WaveLength      'Calculate what the system clock's value will
                                   'be at the end of this cycle's period
    waitcnt(period)                'Wait for the system counter to reach the
                                   '"period" value (end of cycle)
                                  



{{09 Sep 09       Harprit Sandhu
StepperFromPot.spin
Propeller Tool Ver 1.2.6
Chapter 26 Program 4

RUNNING A STEPPER MOTOR FROM A POTENTIOMETER
UNI-DIRECTIONAL CONTROL

This program allows you to control the speed of a STEPPER motor
from a potentiometer

Xavien amplifier lines are
Coil #1                                    
   Brake is on     line P2 of the propeller
   PWM is on       line P3 of the propeller
   Direction is on line P4 of the propeller
Coil #2                                      
   Brake is on     line P5 of the propeller 
   Direction is on line P6 of the propeller  
   PWM is on       line P7 of the propeller
  
}}
CON                                                                   
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000
  Brk1=2
  Pwm1=Brk1+1
  Dir1=Brk1+2
  Dir2=Brk1+3
  Brk2=Brk1+4
  Pwm2=Brk1+5     
 
VAR                      'these are the variables we will use.
  long stack1[35]        'space for Cog_LCD         
  long stack2[35]        'space for Cog MoveStepper
  word Pcount            'potentiometer reading
 
OBJ                      'These are the methods we will need
  LCD  : "LCDRoutines4"  'for the LCD methods
  UTIL : "Utilities"     'for general methods
  
PUB Go                          'main cog
  cognew(MoveStepper,@Stack1)  
  cognew(cog_LCD,    @stack2)   'start a new cog for the LCD                                       
  repeat                        'this main cog's main loop   
    pcount:=UTIL.read3202_0 + 1 'get the pot reading from the utilities
                                'the 1 eliminates a 0 reading
    
Pub cog_LCD                        'set up and run the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Div Fac=" )) 'Potentiometer position ID
    LCD.PRINT_DEC(pcount)          'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (2,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Mtr Rpm=" )) 'Potentiometer position ID
    LCD.PRINT_DEC(6*pcount/10)     'print rpm 
    LCD.SPACE(2)                   'erase over old data

PUB MoveStepper
  dira[Brk1..Pwm2]~~           
  pcount:=50
  repeat        'BPD DBP            B=Brake, P=PWM, D=direction.  
    outa[Brk1..Pwm2]:=%011_010            'on  off
    waitcnt(clkfreq/(pcount)+cnt)    '
    outa[Brk1..Pwm2]:=%100_101            'off on
    waitcnt(clkfreq/(pcount)+cnt)    '
    outa[Brk1..Pwm2]:=%010_010            'rev off
    waitcnt(clkfreq/(pcount)+cnt)    '
    outa[Brk1..Pwm2]:=%100_001            'off rev
    waitcnt(clkfreq/(pcount)+cnt)    ' 
    



{{09 Sep 09    Harprit Sandhu
StepperFwdRev.spin 
Propeller Tool Ver 1.2.6
Chapter 26 Program 5

RUNNING A STEPPER MOTOR FROM A POTENTIOMETER
Fwd-Rev control From Pot 1
Speed control from Pot 2
 
Xavien amplifier lines are
Coil #1                                    
   Brake is on     line P2 of the propeller
   PWM is on       line P3 of the propeller
   Direction is on line P4 of the propeller
Coil #2                                      
   Brake is on     line P5 of the propeller 
   Direction is on line P6 of the propeller  
   PWM is on       line P7 of the propeller
  
}}
CON                                                                   
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000
  Brk1=2                         'line assignments
  Pwm1=Brk1+1
  Dir1=Brk1+2
  Dir2=Brk1+3
  Brk2=Brk1+4
  Pwm2=Brk1+5     
  divmin = 4
  divmax = 4500
 
VAR                      'these are the variables we will use.
  long stack2[25]        'space for Cog_LCD                     
  long stack3[25]        'space for Cog MoveStepper
  byte Pcount            'potentiometer reading.
  word divider           'divides clkfreq for delays
  byte direction         'stepper direction
  long range
 
OBJ                      'These are the methods we will need
  LCD  : "LCDRoutines4"   'for the LCD methods
  UTIL : "Utilities"      'for general methods
  
PUB Go                          'main Cog
  Cognew(MoveStepper,@Stack3)  
  Cognew(cog_LCD,    @stack2)   'start a new Cog for the LCD 
  repeat                        'this main Cog's main loop   
    pcount:=UTIL.Read3202_0/16  'get the pot reading from the utilities 
    range:=UTIL.Read3202_1+10   'get the pot reading for range
    if pcount<128
      pcount:=127-pcount
      direction:=0
    else              
      pcount:=pcount-128
      direction:=1                            
    if range<divmin                'check min
      range:=divmin                'set min
    if range>divmax                'check max
      range:=divmax                'set max
    divider:=range                 'set divider value

Pub cog_LCD                        'set up and run the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Div Fac=" )) 'Potentiometer position ID
    LCD.PRINT_DEC(pcount)          'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (2,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Mtr Rpm=" )) 'Potentiometer position ID
    LCD.PRINT_DEC(range)           'print range/pot 
    LCD.SPACE(2)                   'erase over old data 

PUB MoveStepper
  dira[Brk1..Pwm2]~~
  outa[Brk1..Pwm2]~~                                         
  divider:=500
  repeat
    if direction==0
      outa[Brk1..Pwm2]:=%011_010            'on  off
      waitcnt(clkfreq/divider+cnt)          '      
     outa[Brk1..Pwm2]:=%100_001             'off rev
      waitcnt(clkfreq/divider+cnt)          '         
      outa[Brk1..Pwm2]:=%010_010            'rev off
      waitcnt(clkfreq/divider+cnt)          '
      outa[Brk1..Pwm2]:=%100_101            'off on           
      waitcnt(clkfreq/divider+cnt)          '        
    else                                    '
      outa[Brk1..Pwm2]:=%011_010            'on  off
      waitcnt(clkfreq/divider+cnt)          '
      outa[Brk1..Pwm2]:=%100_101            'off on
      waitcnt(clkfreq/divider+cnt)          '
      outa[Brk1..Pwm2]:=%010_010            'rev off
      waitcnt(clkfreq/divider+cnt)          '
      outa[Brk1..Pwm2]:=%100_001            'off rev
      waitcnt(clkfreq/divider+cnt)          '        





{{10 Sep 09  Harprit Sandhu
StepperDistPot.spin
Propeller Tool Ver 1.2.6
Chapter 26 Program 6

RUNNING A STEPPER MOTOR FROM A POTENTIOMETER
STEPPER position FOLLOWS POT position

This program allows you to control the speed of a STEPPER motor
from a potentiometer and run motor back and forth

Xavien amplifier lines are
Coil #1                                    
   Brake is on     line P2 of the propeller
   PWM is on       line P3 of the propeller
   Direction is on line P4 of the propeller
Coil #2                                      
   Brake is on     line P5 of the Propeller 
   Direction is on line P6 of the Propeller  
   PWM is on       line P7 of the propeller  
}}

CON                                                                       
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000 
  Brk1=2                         'line assignments
  Pwm1=Brk1+1
  Dir1=Brk1+2
  Dir2=Brk1+3
  Brk2=Brk1+4
  Pwm2=Brk1+5         
  
VAR                      'these are the variables we will use.
  long stack2[35]        'space for Cog_LCD                     
  long stack3[35]        'space for Cog MoveStepper
  byte Pcount            'potentiometer reading.
  word divider           'divides clkfreq for delays
  byte servopos          'servo position
  
OBJ                      'These are the methods we will need
  LCD  : "LCDRoutines4"  'for the LCD methods
  UTIL : "Utilities"     'for general methods
  
PUB Go                          'main Cog
  Cognew(MoveStepper,@Stack3)  
  Cognew(cog_LCD,    @stack2)   'start a new Cog for the LCD
  servopos:=32                  'any non 0 OK
  repeat                        'this main Cog's main loop   
    pcount:=UTIL.Read3202_0/16  'get the pot reading from the utilities
    repeat 8                    'do 8 at at ime to speed thing up
      MoveStepper               'move motor

Pub Cog_LCD                        'set up and run the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (2,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Target  =" ))     'Potentiometer position ID
    LCD.PRINT_DEC(pcount)          'print the pot reading 
    LCD.SPACE(5)                   'erase over old data         
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Position=" ))     'Potentiometer position ID
    LCD.PRINT_DEC(servoPos)         'print the pot reading 
    LCD.SPACE(5)                    'erase over old data 

Pub MoveStepper                     'stepper move routine
  dira[Brk1..Pwm2]~~                'set at outputs
  outa[Brk1..Pwm2]~~                'set high
  divider:=750                      'max acceptable divider
  case servopos-pcount    'this is the error in the position      
     -1..-255:            'neg error move to + direction
        outa[Brk1..Pwm2]:=%011_010            'on  off
        waitcnt(clkfreq/divider+cnt)    '
        outa[Brk1..Pwm2]:=%100_101            'off on
        waitcnt(clkfreq/divider+cnt)    '
        outa[Brk1..Pwm2]:=%010_010            'rev off
        waitcnt(clkfreq/divider+cnt)    '
        outa[Brk1..Pwm2]:=%100_001            'off rev
        waitcnt(clkfreq/divider+cnt)    ' 
        servoPos:=servoPos+1   
     0:                   'no error so do nothing
     1..255:              'pos error so move in- direction
        outa[Brk1..Pwm2]:=%011_010            'on  off
        waitcnt(clkfreq/divider+cnt)    '      
        outa[Brk1..Pwm2]:=%100_001            'off rev
        waitcnt(clkfreq/divider+cnt)    '         
        outa[Brk1..Pwm2]:=%010_010            'rev off
        waitcnt(clkfreq/divider+cnt)    '
        outa[Brk1..Pwm2]:=%100_101            'off on           
        waitcnt(clkfreq/divider+cnt)    '        
        servoPos:=servoPos-1
          




{{10 Sep 09  Harprit Sandhu
StepBackForthPot.spin
Propeller Tool Ver 1.2.6
Chapter 26 Program 8

RUNNING A STEPPER MOTOR FROM A POTENTIOMETER
MOVES BACK AND FORTH
Po1 1 controls distance
Pot 2 controls max speed.

Xavien amplifier lines are same as before
Coil #1                                    
   Brake is on     line P2 of the propeller
   PWM is on       line P3 of the propeller
   Direction is on line P4 of the propeller
Coil #2                                      
   Brake is on     line P5 of the Propeller 
   Direction is on line P6 of the Propeller  
   PWM is on       line P7 of the propeller
  
}}
CON                                                                          
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000   
  Brk1=2                         'line assignments
  Pwm1=Brk1+1
  Dir1=Brk1+2
  Dir2=Brk1+3
  Brk2=Brk1+4
  Pwm2=Brk1+5
  divstt  = 200          'starting speed
 
VAR                      'these are the variables we will use.
  long stack2[25]        'space for Cog_LCD                     
  long stack3[25]        'space for Cog MoveStepper
  word Pcount            'potentiometer reading.
  word divider           'divides clkfreq for delays
  word divmax            '
  
OBJ                      'These are the methods we will need
  LCD  : "LCDRoutines4"   'for the LCD methods
  UTIL : "Utilities"     'for general methods
  
PUB Go                          'main Cog
  Cognew(MoveStepper,@Stack3)   'start new Cog for stepper moves
  Cognew(cog_LCD,    @stack2)   'start a new Cog for the LCD 
  repeat                        'this main Cog's main loop   
    pcount:=UTIL.Read3202_0/4   '                             
    divmax:=100*UTIL.Read3202_1*2/82+2   'max ia 10000
   
Pub Cog_LCD                        'set up and run the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Div =" ))    'Potentiometer position ID
    LCD.PRINT_DEC(divider)         'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (1,12)            'Go to 1st line 1st space
    LCD.PRINT_DEC(divmax)          'max division                       
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (2,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Dist=" ))    'Potentiometer position ID
    LCD.PRINT_DEC(pcount)          'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (2,12)            'Go to 1st line 1st space
    LCD.PRINT(STRING("Max"))       'max division                       
    LCD.SPACE(2)                   'erase over old data 

PUB MoveStepper
  dira[BRK1..PWM2]~~
  outa[BRK1..PWM2]~~                                         
  divider:=divstt
  repeat       
    repeat pcount
      divider:=divider*divstt/(divstt-10)
      if divider>divmax
        divider:=divmax               'BPD DBP B=Brake,P=PWM,D=direction.
      outa[BRK1..PWM2]:=%011_010            'on  off
      waitcnt(clkfreq/divider+cnt)    '
      outa[BRK1..PWM2]:=%100_101            'off on
      waitcnt(clkfreq/divider+cnt)    '
      outa[BRK1..PWM2]:=%010_010            'rev off
      waitcnt(clkfreq/divider+cnt)    '
      outa[BRK1..PWM2]:=%100_001            'off rev
      waitcnt(clkfreq/divider+cnt) '
   divider:=divstt
   waitcnt(clkfreq/3+cnt)
                              
    repeat pcount                                     
      divider:=divider*divstt/(divstt-10)
      if divider>divmax
        divider:=divmax
      outa[BRK1..PWM2]:=%011_010            'on  off
      waitcnt(clkfreq/divider+cnt)    '
      outa[BRK1..PWM2]:=%100_001            'off on
      waitcnt(clkfreq/divider+cnt)    '
      outa[BRK1..PWM2]:=%010_010            'rev off
      waitcnt(clkfreq/divider+cnt)    '
      outa[BRK1..PWM2]:=%100_101            'off rev
      waitcnt(clkfreq/divider+cnt) '
   divider:=divstt
   waitcnt(clkfreq/3+cnt)       





{{24 Sep 09     Harprit Sandhu
StepFromPot.spin
Propeller Tool Ver. 1.2.6
Chapter 26 Program 9

Running a stepper motor from a potentiometer
Moves back and forth a variable distance
Max speed fixed but can be changed at divmax constant
Control distance moved with the potentiometer.
Finished program  

This program allows you to control the distance moved by a STEPPER
motor from a potentiometer as it moves back and forth automatically
The number of steps it goes up and down is determined by the pot
and is initially set for a maximum move of ~100 turns for a motor
with 100 steps per revolution. (which I was using).
Display shows the divider value used and Pot reading

Xavien amplifier lines
Coil #1   
   Brake is on     line P2 of the propeller
   PWM is on       line P3 of the propeller
   Direction is on line P4 of the propeller
Coil #2  
   Brake is on     line P5 of the Propeller 
   Direction is on line P6 of the Propeller  
   PWM is on       line P7 of the propeller
  
}}
CON    
  _CLKMODE=XTAL1+ PLL2X  'The system clock spec
  _XINFREQ     =5_000_000
  divmax       =8000          'the higher this is the faster the speed
  divstart     =200           'starting speed
  divDecrement =20            'rate at which speed changes
 
VAR                      'these are the variables we will use.
  long stack1[35]        'space for Cog_LCD  
  long stack2[35]        'space for Cog MoveStepper
  word Pcount            'potentiometer reading.
  word divider           'divides clkfreq for delays 

OBJ                      'These are the methods we will need 
  LCD  : "LCDRoutines4"  'for the LCD methods
  UTIL : "Utilities"     'for general methods
  
PUB Go                          'main Cog 
  Cognew(cog_LCD,    @stack1)   'start a new Cog for the LCD   
  Cognew(MoveStepper,@Stack2)   'start new Cog for stepper moves
  repeat                        'this is main Cogs main loop   
    pcount:=UTIL.read3202_0/4+1 'get the pot reading from the utilities
   
PRI Cog_LCD                        'set up and run the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Div =" ))    'dividing value
    LCD.PRINT_DEC(divider)         'print valoue 
    LCD.SPACE(5)                   'erase over old data
    LCD.POSITION (2,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Dist=" ))    'Distance moved
    LCD.PRINT_DEC(pcount)          'print value 
    LCD.SPACE(5)                   'erase over old data     

PRI MoveStepper                    '
  dira[2..7]~~                     'all outputs
  outa[2..7]~~                     'all high                    
  divider:=divstart                'set starting point for div
  repeat                           'outer loop 
    repeat pcount                  'move loop, forward
      divider:=divider*divstart/(divstart-divDecrement)
      if divider>divmax               'check div
        divider:=divmax               'clamp div
      outa[2..7]:=%011_010            'on  off
      waitcnt(clkfreq/divider+cnt)    '
      outa[2..7]:=%100_101            'off on  
      waitcnt(clkfreq/divider+cnt)    '
      outa[2..7]:=%010_010            'rev off
      waitcnt(clkfreq/divider+cnt)    '
      outa[2..7]:=%100_001            'off rev
      waitcnt(clkfreq/divider+cnt)    '
    divider:=divstart                  'reset divider
    waitcnt(clkfreq/8+cnt)
                             
    repeat pcount                     'move loop, backwards   
      divider:=divider*divstart/(divstart-divDecrement)
      if divider>divmax               'check div
        divider:=divmax               'clamp div
      outa[2..7]:=%011_010            'on  off
      waitcnt(clkfreq/divider+cnt)    '
      outa[2..7]:=%100_001            'off on
      waitcnt(clkfreq/divider+cnt)    '
      outa[2..7]:=%010_010            'rev off
      waitcnt(clkfreq/divider+cnt)    '
      outa[2..7]:=%100_101            'off rev
      waitcnt(clkfreq/divider+cnt)     
    divider:=divstart                 'reset divider
    waitcnt(clkfreq/8+cnt)





{{4 Sep 09       Harprit Sandhu
MotorHoldPos.Spin
Propeller Tool Version 1.2.6
Chapter 27 Program 01, 02, 03 depending on gain algorithm in use

This program holds and encoded motor at the starting position.
If you disturb the motor it will return to its initial position.
You may have to adjust the gain variable for your particular motor
You adjust it with POT1. Low values are needed or the motor
oscillates

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4

Potentiometer read through MCP3202 at P18..P21

LCD on the usual      P12..P18 standard. Set Up.

Revisions
OCT 29 08  Revisions to make variable universal
           added software runaway IF on motor direction
DEC 24 09  Changed to 3202 pots. Uses PotOne
          
}}
OBJ
  Encoder : "Quadrature Encoder" 'for encoder readings
  LCD     : "LCDRoutines4"       'for the LCD methods
  UTIL    : "Utilities"          'for general methods
                                                    
CON                                                                   
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ    = 5_000_000
  MotorRev    =1  'set this to 0 to reverse a runaway motor
                  'set to 1 for normal operations.
                  'You can also fix this runaway by reversing
                  'the encoder leads S1 and S2.
  BRK      =2     'Connections to the amplifier
  PWM      =BRK+1 'next line
  DIR      =BRK+2 'next line
                 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain
  long Pulswidth          'pulse width
  long PresPosition       'Present Position
  long TargetPosition     'Target Position
  long PositionError      'Positional errro
  long MinGain            'Minimum gain
  long Gain               'Actual gain used
  long MaxGain            'Maxim gain permitted 
  long Index              'Countin ginded
  word Integ              'Integration value
  word PotOne             'Potentiometer reading
                                            
PUB Go                                                           
  cognew(Cog_LCD,             @stack2)              
  cognew(Cog_SetMotPower,     @stack3)
  cognew(Cog_RunMotor(PWM),   @Stack4)
  cognew(Cog_FigGain,         @stack5)
  Encoder.Start(0, 1, 0, @Pos)     'Read the encoder position                     
  MaxGain:=2000               'Maxim gain
  MinGain:=100                'Minimum gain
  repeat
    PotOne:=UTIL.Read3202_0   'Read pot
    
PRI cog_LCD                        'manage the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Err=" ))     'Error id
    LCD.PRINT_DEC(PositionError)   'print error
    LCD.SPACE(2)                   'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))    'Potentiometer
    LCD.PRINT_DEC(gain)            'print the gain 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (1,11)            'Go to 2nd line 1st space
    LCD.PRINT(STRING("Integ"))     'integrated value
    LCD.SPACE(1)                   'set position for cursor 
    LCD.POSITION (2,11)            'Go to 2nd line 1st space
    LCD.PRINT_DEC(Integ)           'print the integ
    LCD.SPACE(2)                   'erase over old data
 
PUB Cog_SetMotPower
  dira[BRK..DIR]~~                 'These pins control the motor amp      
  TargetPosition:=0                'we want to stay where we are
  outa[BRK]~                       'turn off the amp brake
  repeat                           'loop
    PresPosition:=pos[0]           'reads the encoder position
    PositionError:=TargetPosition-PresPosition
    case PositionError             'decision variable
      -1_000_000..-1:              'range
        if MotorRev                'negative range
           outa[DIR]~~             'move positive
        else                       'decide
           outa[DIR]~              'move negative
        PULSWIDTH:=gain*244/10     'set gain
      -0..0 :                      'range for stopping
         PULSWIDTH:=0              'gain is set to 0
      1..1_000_000:                'range
        if MotorRev                'positive range          
           outa[DIR]~              'move negative
        else                       'decide
           outa[DIR]~~             'move positive
        PULSWIDTH:=gain*244/10     'set gain
   
PUB Cog_RunMotor(Pin)|WaveLength,period  'subroutine to toggle the output line
  dira[BRK..DIR]~~                 'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin# here  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with pulsewidth=0
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for the wavelength
   
PRI Cog_FigGain                     'The Cog we are playing with
  repeat                            'loop
    gain:=PotOne                    'how we define gain here
 
{{EXERCISE: Play with the equation on the last line to see what happens
to the motor response.

Turn power to motor off and then turn motor by hand and watch what the
LCD shows and look at PWM line P3 to see what the power to the motor
does while you turn POT1

We will be using this set up a lot so leave it all hooked up
}}

    


{{4 Sep 09       Harprit Sandhu
MotorHoldPotPos.Spin
Propeller Tool Version 1.2.6
Chapter 28 Program 01

This program moves the encoded motor to a position controlled
by a potentiometer. Range is 4095 encoder counts. This makes a
servo like an R/C hobby servo only much much more powerful.
You may have to adjust the gain variable for your particular motor

Connections are
Amplifier brake         P2
Amplifier PWM           P3
Amplifier direction     P4

Potentiometer 3202      P19..P22

LCD on the usual   P12..P18

Revisions
Oct 09 08  Revisions to make variables universal
           Added software runaway fin on motor direction
Dec 24 09  Changed over to 4095 pots
          
}}
OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4"       'for the LCD methods
  UTIL    : "Utilities"          'for general methods
                                                    
CON                                                                   
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ    = 5_000_000
  MotorRev    =1              'set this to 0 to reverse a runaway motor
                              'set to 1 for normal operations.
                              'You can also fix this runaway by reversing
                              'encoder leads.
  BRK      =2
  PWM      =BRK+1
  DIR      =BRK+2
                 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain
  long Pulswidth          '
  long PresPosition       '
  long initPosition       '
  long TargetPosition     '
  long PositionError      '
  long MinGain            '
  long Gain               '
  long MaxGain            ' 
  long Index              '
  word Integ              '
  word PotOne             '
                                            
PUB Go                                                           
  cognew(Cog_LCD,             @stack2)              
  cognew(Cog_SetMotPower,     @stack3)
  cognew(Cog_RunMotor(PWM),   @Stack4)
  cognew(Cog_FigGain,         @stack5)
  Encoder.Start(0, 1, 0, @Pos)     'Read the encoder position                     
  MaxGain:=2000
  MinGain:=100
  repeat
      PotOne:=UTIL.Read3202_0
   
PRI cog_LCD                        'manage the LCD
pulswidth:=89
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Err=" ))     'Error
    LCD.PRINT_DEC(PositionError)   'print error
    LCD.SPACE(2)                   'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))    'Potentiometer
    LCD.PRINT_DEC(gain)            'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (1,11)            'Go to 2nd line 1st space
    LCD.PRINT(STRING("Integ"))
    LCD.SPACE(1)                   'set position for cursor 
    LCD.POSITION (2,11)            'Go to 2nd line 1st space
    LCD.PRINT_DEC(Integ)           'print the index
    LCD.SPACE(2)                   'erase over old data

PUB Cog_SetMotPower
  dira[BRK..DIR]~~                 'These pins control the motor amp
  outa[BRK]~                       'turn off the amp brake    
  repeat                           'loop                    
    PresPosition:=pos[0]           'reads the encoder position      
    TargetPosition:=InitPosition+PotOne
    PositionError:=TargetPosition-PresPosition
    case PositionError             'decisions variable
      -1000000..-2:
        if MotorRev                'negative range
           outa[DIR]~~             'move positive
        else
           outa[DIR]~              'move negative
        PULSWIDTH:=gain*244/10     'set gain
      -1..0 :                      'range for stopping
         PULSWIDTH:=0              'gain is set to 0
      1..1000000:
        if MotorRev                'positive range          
           outa[DIR]~              'move negative
        else
           outa[DIR]~~             'move positive
        PULSWIDTH:=gain*244/10     'set gain 

PUB Cog_RunMotor(Pin)|WaveLength,period  'subroutine to toggle the output line, set
  dira[BRK..DIR]~~                 'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin# here  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with pulsewidth=0
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for the wavelength

PRI Cog_FigGain
  repeat                           'loop
    if ||PositionError=<1          'if no error
       Integ:=0                    'set the variables to zero
       Index:=0                    'set the variables to zero
    Else                           'Otherwise
      index:=index+1               'increment the index counter
    If index==5                    'when it reaches set value
       integ:=integ+1              'increase the integrating function
       index:=0                    'and reset the index to 0
    if integ > 2000                'set limit on integrated gain
       integ:=2000                 'clamp value
    gain:=8+||positionError+integ  'add it all up for the gain.
    gain:=gain <# MaxGain          'gain must be less than MaxGain

{{EXERCISES:
Play with the equation on the last few line to see what happens
to the motor response to the error signal.
Adjust the
    TargetPosition:=InitPosition+PotOnne
line to see what happens
Work on making the response faster. There is a delay right now.
How do you handle the overshoot when the gain has to increase real
fast?

Disconnect power to motor and turn shaft and watch the LCD and the
oscilloscope to see how  the gain changes as the error changes.
This is very instructive and very important to understand well.
}}




{{4 Sep 09   Harprit Sandhu
MotorHoldPotSpd.Spin
Propeller Tool Version 1.2.6 
Chapter 28 Program 04

This program controls the speed of the motor from a potentiometer.
You may have to adjust the gain variable for your particular motor

Connections are
Amplifier brake         P2
Amplifier PWM           P3
Amplifier direction     P4

Potentiometer          P19

LCD on the usual   P12..P18

Revisions
Oct 09 08  Revisions to make variables universal
           Added software runaway fin on motor direction
Dec 24 09  Changed over to 4095 pots
          
}}
OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4"       'for the LCD methods
  UTIL    : "Utilities"          'for general methods
                                                    
CON                                                                   
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ    = 5_000_000
  MotorRev    =1              'set this to 0 to reverse a runaway motor
                              'set to 1 for normal operations.
                              'You can also fix this runaway by reversing
                              'encoder leads.
  BRK      =2
  PWM      =BRK+1
  DIR      =BRK+2
                 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain
  long Pulswidth          '
  long PresPosition       '
  long initPosition
  long TargetPosition     '
  long PositionError      '
  long MinGain            '
  long Gain               '
  long MaxGain            ' 
  long Index              '
  word Integ              '
  word PotOne             '
                                            
PUB Go                                                           
  cognew(Cog_LCD,             @stack2)              
  cognew(Cog_SetMotPower,     @stack3)
  cognew(Cog_RunMotor(PWM),   @Stack4)
  cognew(Cog_FigGain,         @stack5)
  Encoder.Start(0, 1, 0, @Pos)     'Read the encoder position                     
  MaxGain:=2000
  MinGain:=100         
  TargetPosition:=0                'we want to stay where we are
  repeat
      PotOne:=UTIL.Read3202_0
   
PRI cog_LCD                        'manage the LCD
pulswidth:=89
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Err=" ))     'Error
    LCD.PRINT_DEC(PositionError)   'print error
    LCD.SPACE(2)                   'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))    'Potentiometer
    LCD.PRINT_DEC(gain)            'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (1,11)            'Go to 2nd line 1st space
    LCD.PRINT(STRING("Integ"))
    LCD.SPACE(1)                   'set position for cursor 
    LCD.POSITION (2,11)            'Go to 2nd line 1st space
    LCD.PRINT_DEC(Integ)           'print the index
    LCD.SPACE(2)                   'erase over old data
 
PUB Cog_SetMotPower
  dira[BRK..DIR]~~                 'These pins control the motor amp
  outa[BRK]~                       'turn off the amp brake
  repeat                           'loop
    PresPosition:=pos[0]           'reads the encoder position
    TargetPosition:=TargetPosition+PotOne/256/3
    PositionError:=TargetPosition-PresPosition
    case PositionError             'decision variable
      -1_000_000..-1:
        if MotorRev                'negative range
           outa[DIR]~~             'move positive
        else
           outa[DIR]~              'move negative
        PULSWIDTH:=gain*244/10     'set gain
      -0..0 :                      'range for stopping
         PULSWIDTH:=0              'gain is set to 0
      1..1_000_000:
        if MotorRev                'positive range          
           outa[DIR]~              'move negative
        else
           outa[DIR]~~             'move positive
        PULSWIDTH:=gain*244/10     'set gain


PUB Cog_RunMotor(Pin)|WaveLength,period  'subroutine to toggle the output line, set
  dira[BRK..DIR]~~                 'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin# here  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with pulsewidth=0
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for the wavelength

PRI Cog_FigGain
  repeat                           'loop
    if ||PositionError=<1          'if no error
       Integ:=0                    'set the variables to zero
       Index:=0                    'set the variables to zero
    Else                           'Otherwise
      index:=index+1               'increment the index counter
    If index==5                    'when it reaches set value
       integ:=integ+1              'increase the integrating function
       index:=0                    'and reset the index to 0
    if integ > 2000                'set limit on integrated gain
       integ:=2000                 'clamp value
    gain:=8+||positionError+integ/4  'add it all up for the gain.
    gain:=gain <# MaxGain          'gain must be less than MaxGain


{{EXERCISES:
Play with the equation on the last few line to see what happens
to the motor response to the error signal.
Adjust the
    TargetPosition:=TargetPosition+PotOne
line to see what happens
Work on making the response faster. There is a delay right now.
How do you handle the overshoot when the gain has to increase real
fast?

Disconnect power to motor and turn shaft and watch the LCD and the
oscilloscope to see how  the gain changes as the error changes.
This is very instructive and very important to understand well.
}}




{{4 Sep 09   Harprit Sandhu
HoldMotorPotSpd.Spin
Propeller Tool Version 1.2.6
Chapter 28sProgram 05

This program controls the speed of the motor from a potentiometer.
You may have to adjust the gain variable for your particular motor

Connections are
Amplifier brake         P2
Amplifier PWM           P3
Amplifier direction     P4

Potentiometer          P19

LCD on the usual   P12..P18

Revisions
Oct 09 08  Revisions to make variables universal
           Added software runaway fin on motor direction
Dec 24 09  Changed over to 4095 pots
          
}}
OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4"       'for the LCD methods
  UTIL    : "Utilities"          'for general methods
                                                    
CON                                                                   
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ    = 5_000_000
  MotorRev    =1              'set this to 0 to reverse a runaway motor
                              'set to 1 for normal operations.
                              'You can also fix this runaway by reversing
                              'encoder leads.
  BRK      =2
  PWM      =BRK+1
  DIR      =BRK+2
                 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain
  long Pulswidth          '
  long PresPosition       '
  long initPosition
  long TargetPosition     '
  long PositionError      '

  long MinGain            '
  long Gain               '
  long MaxGain            ' 
  long Index              '
  word Integ              '
  word PotOne             '
                                            
PUB Go                                                           
  cognew(Cog_LCD,             @stack2)              
  cognew(Cog_SetMotPower,     @stack3)
  cognew(Cog_RunMotor(PWM),   @Stack4)
  cognew(Cog_FigGain,         @stack5)
  Encoder.Start(0, 1, 0, @Pos)     'Read the encoder position                     
  MaxGain:=2000
  MinGain:=100         
  TargetPosition:=0                'we want to stay where we are
  repeat
      PotOne:=UTIL.Read3202_0
   
PRI cog_LCD                        'manage the LCD
pulswidth:=89
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Err=" ))     'Error
    LCD.PRINT_DEC(PositionError)   'print error
    LCD.SPACE(2)                   'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))    'Potentiometer
    LCD.PRINT_DEC(gain)            'print the pot reading 
    LCD.SPACE(2)                   'erase over old data
    LCD.POSITION (1,11)            'Go to 2nd line 1st space
    LCD.PRINT(STRING("Integ"))
    LCD.SPACE(1)                   'set position for cursor 
    LCD.POSITION (2,11)            'Go to 2nd line 1st space
    LCD.PRINT_DEC(Integ)           'print the index
    LCD.SPACE(2)                   'erase over old data
 
PUB Cog_SetMotPower
  dira[BRK..DIR]~~                 'These pins control the motor amp
  outa[BRK]~                       'turn off the amp brake
  repeat                           'loop
    PresPosition:=pos[0]           'reads the encoder position
    TargetPosition:=TargetPosition+PotOne/256/3
    PositionError:=TargetPosition-PresPosition
    case PositionError             'decision variable
      -1_000_000..-1:
        if MotorRev                'negative range
           outa[DIR]~~             'move positive
        else
           outa[DIR]~              'move negative
        PULSWIDTH:=gain*244/10     'set gain
      -0..0 :                      'range for stopping
         PULSWIDTH:=0              'gain is set to 0
      1..1_000_000:
        if MotorRev                'positive range          
           outa[DIR]~              'move negative
        else
           outa[DIR]~~             'move positive
        PULSWIDTH:=gain*244/10     'set gain


PUB Cog_RunMotor(Pin)|Cycle_time,period  'subroutine to toggle the output line, set
  dira[BRK..DIR]~~                 'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin# here  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with pulsewidth=0
  Cycle_time:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+Cycle_time      'Calculate cycle time
    waitcnt(period)                'Wait for the cycle time

PRI Cog_FigGain
  repeat                           'loop
    if ||PositionError=<1          'if no error
       Integ:=0                    'set the variables to zero
       Index:=0                    'set the variables to zero
    Else                           'Otherwise
      index:=index+1               'increment the index counter
    If index==5                    'when it reaches set value
       integ:=integ+1              'increase the integrating function
       index:=0                    'and reset the index to 0
    if integ > 2000                'set limit on integrated gain
       integ:=2000                 'clamp value
    gain:=8+||positionError+integ/4  'add it all up for the gain.
    gain:=gain <# MaxGain          'gain must be less than MaxGain

{{EXERCISES:
Play with the equation on the last few line to see what happens
to the motor response to the error signal.
Adjust the
    TargetPosition:=TargetPosition+PotOne
line to see what happens
Work on making the response faster. There is a delay right now.
How do you handle the overshoot when the gain has to increase real
fast?

Disconnect power to motor and turn shaft and watch the LCD and the
oscilloscope to see how  the gain changes as the error changes.
This is very instructive and very important to understand well.
}}





{{14 Sep 09       Harprit Sandhu
MotorHoldPotSpdDir.Spin
Propeller Tool Version 1.2.6
Chapter 28  Program 6     

This program runs the motor back or forth at a speed and direction
as controlled by the potentiometer.

You may have to adjust the gain variable for your particular motor

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4

Potentiometer         P19

LCD on the usual P12..P18

Revisions

}}

OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4" 'for the LCD methods
  UTIL    : "Utilities"  'for general methods

VAR
  long     Pos[3]         'Create buffer for two encoders
                          'plus room for delta position support of 1st encoder)
  long stack2[35]         'space for Cog                                                                                   
  long stack3[35]         'space for Cog                                                                                   
  long stack4[35]         'space for Cog
  word pcount             ' 
  long pulswidth          ' 
  word dcount
  
CON                                                                            
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000 
  PotMax   = 100         'The maximum power to the motor OUT OF 255
  PotMin   = 0           'The minimum power to the motor OUT OF 255
  AmpBrk   = 2
  AmpPWM   = AmpBrk+1
  AmpDir   = AmpBrk+2
 
PUB Go                                                           
  cognew(cog_LCD, @stack2)         'start a new cog      
  cognew(SetMotorPower, @stack3)   'start a new cog
  cognew(RunMotor(AmpPWM),@Stack4)      'start a new cog
  Encoder.Start(0, 1, 0, @Pos)     'read encoder                      
  dira[AmpBrk]~~                   'make output                     
  outa[AmpBrk]~                    'turn brake off
  
PUB SetMotorPower
dira[AmpDir]~~
pos[0]:=0
  repeat                                                                 
    pcount:=UTIL.Read3202_0/16    'get the pot reading from the utilities
    case pcount                 'depends on pcount
      0..127:                   'check for center position
        outa[AmpDir]~           'forward direction set
        pcount:=(127-pcount)*2  'set center and double the 127 to get near 255
      128..129:                 'zero position
        pcount:=0               'clamp to 0
      130..255:                 'or
        outa[AmpDir]~~          'reverse direction
        pcount:=(pcount-128)*2  'set center and double the 127 to get near 255     
    if pcount<PotMin            'check Min value
       pcount:=Potmin           'Clamp to Min value
    if pcount>PotMax            'check Max value
        pcount:=Potmax          'clamp to Max value
    PulsWidth:=pcount*450       'multiply reading to get higher count needed
    dcount:=pcount
   
PRI cog_LCD  
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("EncCnt=" ))  'Potentiometer position ID
    LCD.PRINT_DEC(Pos[0])          'print the pot reading 
    LCD.SPACE(3)                   'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Pot   =" ))  'Potentiometer position ID
    LCD.PRINT_DEC(dcount)          'print the pot reading 
    LCD.SPACE(3)                   'erase over old data

PUB RunMotor(Pin)|WaveLength,period   'subroutine to toggle the output line, set
  dira[2..4]~~                     'gain access to these three amplifier lines      
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                     
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin              
  frqa:=1                          'Set this counter's frqa value to 1              
  PulsWidth:=0                     'Start with position=0                           
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms       
  period:=cnt                      'Store the current value of the counter          
  repeat                           'power PWM routine.                              
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts         
    period:=period+WaveLength      'Calculate wave length                           
    waitcnt(period)                'Wait for the wavelength


{{04 Nov 09   Harprit Sandhu
MotorBckForPotGain.Spin
Propeller Tool Version 1.2.6
Chapter 28  Program 7

This program runs the motor back and forth a while you vary
the gain and distance moved with two potentiometers.
Pot1 controls the distance and
Pot2 controls the gain.
How we control the gain is determined by the method that
sets the gain at the bottom of the programs

We will use the information gained here to design the equations
to set the gain to make the move as fast as possible without
overshoot.

You may have to adjust the parameters for your particular motor

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4

Potentiometer        P19

LCD on the usual P8..P18

}}
OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4" 'for the LCD methods
  UTIL    : "Utilities"  'for general methods
                                                    
CON                                                                  
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000
 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain                                                                               
  long stack6[25]         'space for Cog_Start                                                                                
  long stack7[25]         'space for readpots
  long pulswidth          '
  long PresentPosition    '
  long TargetPosition     '
  long PositionError      '
  long gain               '
  long dgain              'displayed gain
  word PotReading         '
  word startFlag          '
  long startPosition      '
  long distance           '
  long pot1               '
  long Pot2               '
                                                      
PUB Go                                                           
  cognew(cog_LCD, @stack2)              
  cognew(SetMotorPower, @stack3)
  cognew(RunMotor(3),@Stack4)
  cognew(figureGain,  @stack5)
  cognew(StrtFlag,  @stack6)  
  cognew(ReadPots,  @stack7)                                
  Encoder.Start(0, 1, 0, @Pos)  'Reads the encoder position
  startPosition:=Pos[0]         'position read
  distance:=42*0                'number of 1/4th revs is 8 for 1 rev
  repeat                                                                          
    targetPosition:=StartPosition+distance       
    waitcnt(24_000+cnt)
    repeat while startFlag==0
    {The start flag is needed to make sure that one instruction
    gets done before the nexst instructions starts. This is
    managed with the start flag. Try eliminating these
    instructions to see what happens. Is there a better way to
    manage this. As long as the start flag is 0 the program holds
    at this line. It took me a while to get this one figured out!
    }       
    waitcnt(2_000_000+cnt)       
    targetPosition:=startPosition      
    waitcnt(24_000+cnt)
    repeat while startFlag==0       
    waitcnt(2_000_000+cnt)            

PRI SetMotorPower
  dira[2..4]~~                      'These pins control the motor amp
  repeat                            'loop     
    PresentPosition:=pos[0]         'read the encoder position
    PositionError:=TargetPosition-PresentPosition
    case PositionError              'decision variable
      -100_000_000..-2:             'negative range
         outa[4]~~                  'move in position direction
         PULSWIDTH:=gain*450        'set gain
      -1..1 :                       'range for stopping
         PULSWIDTH:=0*450           'gain is 0
      2..100_000_000:               'positive range
         OUTA[4]~                   'move in negative direction
         PULSWIDTH:=gain*450        'set gain

PRI cog_LCD                         'manage the LCD
  LCD.INITIALIZE_LCD                'initialize the LCD
  repeat                            'LCD loop  
    LCD.POSITION (1,1)              'Go to 1st line 1st space
    LCD.PRINT(STRING("Er=" ))       'Error
    LCD.PRINT_DEC(PositionError)    'print error
    LCD.SPACE(2)                    'erase over old data    
    LCD.POSITION (1,10)             'Go to 1st line 1st space
    LCD.PRINT_DEC(pot1)             'print error
    LCD.SPACE(2)                    'erase over old data
    LCD.POSITION (1,14)             'Go to 1st line 1st space
    LCD.PRINT_DEC(pot2)             'erase over old data
    LCD.SPACE(2)                    'erase over old data     
    LCD.POSITION (2,1)              'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))     'Potentiometer
    LCD.PRINT_DEC(dgain)            'print the pot reading 
    LCD.SPACE(2)                    'erase over old data
    LCD.POSITION (2,10)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Start=" ))    'Potentiometer  
    LCD.PRINT_DEC(StartFlag)        'print the pot reading 
    distance:=pot1*21    
   
   
PRI RunMotor(Pin)|WaveLength,period  'subroutine to toggle the output line, set
  dira[2..4]~~                     'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin=3  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with position=0
  WaveLength:=clkfreq/100          'Set the time for the wave L to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for end of wavelength

PRI StrtFlag                 'used to determine if motor completed move
  repeat        
    if ||PositionError<2     'is move almost done
      startFlag:=1           'if it is its ok to start
    else                     '1f not
      startFlag:=0           'do not start next move

PUB figureGain                'power to motor
  repeat                      'loop            
    case ||PositionError      'pot is NOT READ
      0..20:gain:=pot2/10           'in these comparisons
      21..80:gain:=pot2/4          'the gain is set by the
      81..200:gain:=pot2/2        'amount of the error
      101..80000:gain:=pot2     'in the position.
    gain#>=8
    dgain:=gain

PRI Readpots
  repeat
    pot1:=UTIL.Read3202_0/16 
    pot2:=UTIL.Read3202_1/16
   





{{14 Sep 09   Harprit Sandhu
MotorBakForPlayGain.Spin 
Propeller Tool Version 1.2.6
Chapter 28  Program 8

This program runs the motor back and forth a fixed number
of counts while you can vary the gain with the equations
at the bottom of the programs to see what happens to
the motor dampening function.  We will use the information
gained here to design the equations to set the gain to make
the move as fast as possible without overshoot.

You may have to adjust the parameters for your particular motor

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4
Potentiometer        P19
LCD on the usual P8..P18
}}
OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4" 'for the LCD methods
  UTIL    : "Utilities"  'for general methods
                                                    
CON                                                                  
  _CLKMODE=XTAL1+ PLL2X   'The system clock spec
  _XINFREQ = 5_000_000
  distance =168*8         'full revs
 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain                                                                               
  long stack6[25]         'space for Cog_Start
  long pulswidth          '
  long PresentPosition    '
  long gain               '
  long TargetPosition     '
  long PositionError      '
  byte startFlag          '
  long startPosition      '
                                                        
PUB Go                                                           
  cognew(cog_LCD, @stack2)              
  cognew(SetMotorPower, @stack3)
  cognew(RunMotor(3),@Stack4)
  cognew(figureGain,  @stack5)
  cognew(StaartFlag,  @stack6)                                
  Encoder.Start(0, 1, 0, @Pos)     'Reads the encoder position
  startPosition:=Pos[0]
  repeat                                                                          
    targetPosition:=StartPosition+distance       
    waitcnt(10000+cnt)
    repeat while startFlag==0       
    waitcnt(2_000_000+cnt)       
    targetPosition:=startPosition      
    waitcnt(10000+cnt)
    repeat while startFlag==0       
    waitcnt(2_000_000+cnt)            

PUB SetMotorPower
  dira[2..4]~~                      'These pins control the motor amp
  repeat                            'loop     
    PresentPosition:=pos[0]         'read the encoder position
    PositionError:=TargetPosition-PresentPosition
    case PositionError              'decision variable
      -100_000_000..-2:             'negative range
         outa[4]~~                  'move in position direction
         PULSWIDTH:=gain*450        'set gain
      -1..1 :                       'range for stopping
         PULSWIDTH:=0*450           'gain is 0
      2..100_000_000:               'positive range
         OUTA[4]~                   'move in negative direction
         PULSWIDTH:=gain*450        'set gain

PRI cog_LCD                         'manage the LCD
  LCD.INITIALIZE_LCD                'initialize the LCD
  repeat                            'LCD loop  
    LCD.POSITION (1,1)              'Go to 1st line 1st space
    LCD.PRINT(STRING("Err=" ))      'Error
    LCD.PRINT_DEC(PositionError)    'print error
    LCD.SPACE(5)                    'erase over old data      
    LCD.POSITION (2,1)              'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))     'gain
    LCD.PRINT_DEC(gain)             'print the pot reading 
    LCD.SPACE(2)                    'erase over old data
    LCD.POSITION (2,10)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Start=" ))    'Flag  
    LCD.PRINT_DEC(StartFlag)        'print flag status 

PUB RunMotor(Pin)|WaveLength,period       'subroutine to toggle the output line, set
  dira[2..4]~~                     'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with position=0
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for the wavelength

PUB figureGain                     'power to motor 0-255
  repeat                           'loop   
    case ||PositionError           'pot is NOT READ
      1..20:gain:=6                'in these comparisons
      21..80:gain:=10              'the gain is set by the
      81..200:gain:=40             'amount of the error
      101..80000:gain:=80          'in the position.

PRI StaartFlag             'The start flag is used to inhibit the execution of
  repeat                   'the next move to make sure that each move executes
    if ||PositionError<2   'fully. Then the wait command lets you see that the
      startFlag:=1         'motor actually stopped before proceeding to reversing
    else                   'the motor.  See main Cog above for more.
      startFlag:=0     
                           




{{14 Sep 09   Harprit Sandhu
MotorPotSpeedTable.Spin
Propeller Tool Version 1.2.6
Chapter 28 Program 9

This program controls speed of motor from the pot.
Displays speed and pot setting
You may have to adjust the gain variable for your particular motor

Connections are                   
Encoder 1             P0
Encoder 2             P1
Encoder 3             5 Volts
Encoder 4             Ground
  Also need power and ground for encoder connected
Amplifier brake       P2    Xavien  1
Amplifier PWM         P3    Xavien  2
Amplifier direction   P4    Xavien  3
              
Potentiometer        P19

LCD on the usual P8..P18
The values read are based on a 13.5 volts power
supply for the motor. (Table in book)

}}
OBJ                                       
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4" 'for the LCD methods
  UTIL    : "Utilities"    'for general methods
                                                    
CON                                                                 
  _CLKMODE=XTAL1+ PLL2X         'The system clock spec
  _XINFREQ = 5_000_000

VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain
  long pulswidth          '
  long speed              '
  long start              '
  long end                '
                                                         
PUB Go                                                           
  cognew(cog_LCD, @stack2)              
  cognew(SetMotorPower, @stack3)
  cognew(RunMotor(3),@Stack4)
  cognew(FigureCounts,  @stack5)
  Encoder.Start(0, 1, 0, @Pos)      'Read the encoder position                     

PUB SetMotorPower
  dira[2..4]~~                      'These pins control the motor amp
  repeat                            'loop
    PulsWidth:=Util.Read3202_0/16   'read the 4095 pot position to a byte                

PRI cog_LCD                        'manage the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Speed=" ))   'Error
    LCD.PRINT_DEC(Speed)           'print error
    LCD.SPACE(3)                   'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain =" ))   'Potentiometer
    LCD.PRINT_DEC(pulswidth)            'print the pot reading 
    LCD.SPACE(3)                   'erase over old data

PUB RunMotor(Pin)|Cycle_time,period   'subroutine to toggle the output line, set
  dira[2..4]~~                     'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with position=0
  Cycle_time:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth*24*16         'Send a high pulse for Pulsewidth counts
    period:=period+Cycle_time      'Calculate cycle time
    waitcnt(period)                'Wait for the cycle time

PUB FigureCounts                   'encoder counts
  repeat                           'loop 
    start:=Pos[0]                  'read encoder
    waitcnt(clkfreq+cnt)           'pause 1 sec
    end:=Pos[0]                    'read encoder
    speed:=(end-start)             'counts moved




{{
Chapter 28 Prog 10
}}
PUB FigureGain             'power to motor
  repeat                   'loop
    Case time              'base the gain on the time segment number
      0..50:               'first 50 segments
        gain:=20           'slow speed
      51..150:             'next 100 segments
        gain:=100          'fast speed
      151..200:            'next 50 segments
        gain:=20           'slow speed
      201..300:            'next 100 segments
        gain:=0            'Gain=0 means stop for a while
    waitcnt(120_000+cnt)   'define length of each time segment as 0.1 secs
    time:=time+1           'add to time segment number
    if time==300           'check top time value
      time:=0              'reset time counter




{{4 Sep 09   Harprit Sandhu
MotorSloFstSlo.Spin
Propeller Tool Version 1.2.6
Chapter 28  Program 11

This program moves the motor in a slow, fast ,slow, stop sequence
to demonstrate the control of the speed over a period of equal time
segments. This is an absolutely minimal ramping demonstration. Only
two speeds are used. This could be expanded to a very complicated
algorithm with lots of gains and speed specifications.

We are not using the encoder or the potentiometers in this program.

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4

Potentiometer        P19

LCD on the usual P12..P18 4 bit mode

Revisions


}}
OBJ
  LCD     : "LCDRoutines4" 'for the LCD methods
                                                    
CON                                                                   
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ    = 5_000_000

  AmpBrake    =2
  AmpPWM      =3
  MotorDir    =4
                 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor                                                                                  
  long stack5[25]         'space for Cog_FigureGain
  long gain               '
  long time
  long pulswidth
                                                    
PUB Go                                                           
  cognew(cog_LCD, @stack2)              
  cognew(SetMotorPower, @stack3)
  cognew(RunMotor(AmpPWM),@Stack4)
  cognew(FigureGain,  @stack5)
  repeat
    
PRI cog_LCD                        'manage the LCD
  LCD.INITIALIZE_LCD               'initialize the LCD
  repeat                           'LCD loop  
    LCD.POSITION (1,1)             'Go to 1st line 1st space
    LCD.PRINT(STRING("Time=" )) 'Error
    LCD.PRINT_DEC(time)             'print the pot reading
    LCD.SPACE(2)                    'erase over old data      
    LCD.POSITION (2,1)             'Go to 2nd line 1st space
    LCD.PRINT(STRING("Gain=" ))     'Potentiometer
    LCD.PRINT_DEC(gain)             'print the pot reading 
    LCD.SPACE(2)                    'erase over old data 
   
PUB SetMotorPower
  dira[AmpBrake..MotorDir]~~       'These pins control the motor amp
  outa[AmpBrake]~                  'turn off the amp brake    
  repeat                           'loop     
    outa[MotorDir]~                'move negative
    PULSWIDTH:=gain*450            'set gain          

PUB RunMotor(Pin)|WaveLength,period   'subroutine to toggle the output line, set
  dira[AmpBrake..MotorDir]~~       'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin# here  
  frqa:=1                          'Set this counter's frqa value to 1
  PulsWidth:=0                     'Start with pulsewidth=0
  WaveLength:=clkfreq/50           'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-PulsWidth               'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for the wavelength

PUB FigureGain             'power to motor
  repeat                   'loop
    Case time              'base the gain on the time segment number
      0..100:              'first 50 segments
        gain:=30           'slow speed
      101..200:            'next 100 segments
        gain:=200          'fast speed
      201..300:            'next 50 segments
        gain:=30           'slow speed
      301..399:            'next 100 segments
        gain:=0            'Gain=0 means stop for a while
    waitcnt(120_000+cnt)   'define length of each time segment as 0.1 secs
    time:=time+1           'add to time segment number
    if time==400           'check top time value for reset
      waitcnt(clkfreq/4+cnt) 'wait to look at LCD
      time:=0              'reset time counter
      



{{14 Sep 09   Harprit Sandhu
MotorPositionRC.Spin 
Propeller Tool Version 1.2.6
Chapter 28  Program 14

This program Positions the DC motor from a hobby R/C transmitter
just like it would a R/C hobby servo, but many revs

You may have to adjust the parameters for your particular motor

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4
Radio signal in       P24
LCD on the usual      P8..P18
}}

OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4" 'for the LCD methods
  UTIL    : "Utilities"  'for general methods
                                                    
CON                                                                  
  _CLKMODE=XTAL1+ PLL2X   'The system clock spec
  _XINFREQ = 5_000_000
  BRK      =2
  PWM      =BRK+1
  DIR      =BRK+2
  PulseIn  =24
 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[35]         'space for Cog_LCD                                                                                   
  long stack3[35]         'space for Cog_SetMotorPower                                                                                   
  long stack4[35]         'space for Cog_RunMotor                                                                                       
  long stack5[35]         'space for Cog_Encoder
  long startcycle         '
  long endPulse           '
  long endCycle           '
  long CycleLen           '             
  long PulseLen           '
  long pulswidth
  long freq               '
  long MotPwr             '
  long PresPos
  long TargPos
                                            
PUB Go                                                           
  cognew(cog_LCD,       @stack2)              
  cognew(SetMotorPower, @stack3)
  cognew(PosMotor(3),   @Stack4)
  cognew(Enco,          @Stack5)   
  Encoder.Start(0, 1, 0, @Pos)       'Read the encoder position     
  Dira[PulseIn]~ 
  repeat
    waitpeq(|<PulseIn, |<PulseIn, 0)  'wait for line to go low. 
    waitpeq(0, |<PulseIn, 0)          'wait for line to go low.
    waitpeq(|<PulseIn, |<PulseIn, 0)  'wait for line to go low. 
    startCycle:=CNT                   'read the timer count 0)
    waitpeq(0, |<PulseIn, 0)          'wait for line to go low...                  
    endPulse:=CNT                     'read the timer count for second time
    waitpeq(|<PulseIn, |<PulseIn, 0)  'wait for line to go low.     
    endCycle:=CNT                     'read the timer count for second time           
    pulswidth:=(endPulse-startCycle)  'figure the pulse
    freq:=clkfreq/(endCycle- startCycle)  'figure the freq


PRI cog_LCD                         'manage the LCD
  LCD.INITIALIZE_LCD                'initialize the LCD
  repeat                            'LCD loop  
    LCD.POSITION (1,1)              'Go to 1st line 1st space
    LCD.PRINT(STRING("POSN=" ))     'P0SITION
    LCD.PRINT_DEC(Prespos)          'print position
    LCD.SPACE(2)                    'erase over old data      
    LCD.POSITION (1,11)             'Go to 1st line 11 space
    LCD.PRINT(STRING("DIR=" ))      'Direction of motor power
    LCD.PRINT_DEC(ina[Dir])         'print 
    LCD.SPACE(2)                    'erase over old data      
    LCD.POSITION (2,1)              'Go to 2nd line 1st space
    LCD.PRINT(STRING("TARG=" ))     'TARGET
    LCD.PRINT_DEC(TargPos)          'print  
    LCD.SPACE(2)                    'erase over old data }
   
PUB SetMotorPower
  dira[BRK..DIR]~~                  'These pins control the motor amp 
  repeat                            '
    targPos:=pulswidth/10           'loop     
    if TargPos<PresPos              '
       OUTA[DIR]~~                  '
       dira[BRK]~                   '
       MotPwr:=||(TargPos-PresPos)*200            
    if TargPos==PresPos             '
       dira[BRK]~~                  '
       MotPwr:=0                    '
    if TargPos>PresPos              '
       OUTA[DIR]~                   '
       dira[BRK]~                   '
       MotPwr:=4|(TargPos-PresPos)*200    '                                      

PUB PosMotor(Pin)|WaveLength,period  'subroutine to toggle the output line
  dira[BRK..DIR]~~                 'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin# here  
  frqa:=1                          'Set this counter's frqa value to 1
  motpwr:=0                        'Start with pulsewidth=0
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=-MotPwr                  'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'Wait for the wavelength
 
PRI Enco                                              
  dira[0..1]~                                                 
  repeat
    PresPos:=Pos[0]
                                     



{{14 Sep 09   Harprit Sandhu
MotorSpeedDirRC.Spin 
Propeller Tool Version 1.2.6
Chapter 28  Program 15

This program runs the motor back and forth from a
signal received from a hobby R/C transmitter as would
be use by a servo

You may have to adjust the parameters for your particular motor

Connections are
Amplifier brake       P2
Amplifier PWM         P3
Amplifier direction   P4
Radio signal in       P24
LCD on the usual      P8..P18
}}

OBJ
  Encoder : "Quadrature Encoder"
  LCD     : "LCDRoutines4" 'for the LCD methods
  UTIL    : "Utilities"  'for general methods
                                                    
CON                                                                  
  _CLKMODE=XTAL1+ PLL2X   'The system clock spec
  _XINFREQ = 5_000_000
  BRK      =2
  PWM      =BRK+1
  DIR      =BRK+2
  RadioIn  =24
 
VAR
  long     Pos[3]         'Create buffer for encoder
  long stack2[25]         'space for Cog_LCD                                                                                   
  long stack3[25]         'space for Cog_SetMotorPower                                                                                   
  long stack4[25]         'space for Cog_RunMotor
  long startcycle         '
  long endPulse           '
  long endCycle           '
  long CycleLen           '             
  long PulseLen           '
  long freq               '
  long MotPwr             '
                                                 
PUB Go                                                           
  cognew(cog_LCD,       @stack2)              
  cognew(SetMotorPower, @stack3)
  cognew(RunMotor(3),@Stack4)
  Dira[RadioIn]~
  repeat 
    repeat while ina[RadioIn]==1     'wait for line 1 to go low.
                                     'make sure that we see
                                     'at full wave when we start measuring
    repeat while ina[RadioIn]==0     'wait for line 1 to go low. See Manual   
    startCycle:=CNT                  'read the timer count

    repeat while ina[RadioIn]==1     'wait for line 1 to go hi. See Manual
    endPulse:=CNT                    'read the timer count for second time
     
    repeat while ina[RadioIn]==0     'wait for line 1 to go low. See Manual.
    endCycle:=cnt
   
    PulseLen:=(endPulse-startCycle)/10    'figure the pulse
    CycleLen:=endCycle-startCycle         'figure the cycleLen
    freq:=10_000_000/CycleLen             'figure the freq

PRI cog_LCD                         'manage the LCD
  LCD.INITIALIZE_LCD                'initialize the LCD
  repeat                            'LCD loop  
    LCD.POSITION (1,1)              'Go to 1st line 1st space
    LCD.PRINT(STRING("PWR=" ))      'Power
    LCD.PRINT_DEC(MotPwr)           'print power
    LCD.SPACE(2)                    'erase over old data      
    LCD.POSITION (1,11)             'Go to 1st line 11 space
    LCD.PRINT(STRING("DIR=" ))      'Direction
    LCD.PRINT_DEC(ina[Dir])         'print 
    LCD.SPACE(2)                    'erase over old data      
    LCD.POSITION (2,1)              'Go to 2nd line 1st space
    LCD.PRINT(STRING("WLN=" ))      'Cycle length
    LCD.PRINT_DEC(CycleLen)         'print  
    LCD.SPACE(2)                    'erase over old data
    LCD.POSITION (2,11)             'Go to 2nd line 11 space
    LCD.PRINT(STRING("FRQ=" ))      'Freq  
    LCD.PRINT_DEC(freq)             'print
    LCD.SPACE(2)                    'erase over old data            

PUB SetMotorPower
  dira[BRK..DIR]~~                  'These pins control the motor amp
  repeat                            'loop     
     case pulselen                  '
       300..1500:                   'low vzlues
         outa[DIR]~                 'Motor dir low
         MotPwr:=1500-pulselen      'reset value
       1501..3000:                  'high values
         outa[DIR]~~                'Motor dir hi
         MotPwr:=pulselen-1500      'reset value

PUB RunMotor(Pin)|WaveLength,period   'subroutine to toggle the output line, set
  dira[2..4]~~                     'gain access to these three amplifier lines
  ctra[30..26]:=%00100             'Set this cog's "A Counter" to run PWM                                   
  ctra[5..0]:=Pin                  'Set the "A pin" of this cog to Pin  
  frqa:=1                          'Set this counter's frqa value to 1
  PulseLen:=0                      'Start with position=0
  WaveLength:=clkfreq/100          'Set the time for the pulse width to 10 ms
  period:=cnt                      'Store the current value of the counter
  repeat                           'power PWM routine.
    phsa:=(-MotPwr+70)*50          'Send a high pulse for Pulsewidth counts
    period:=period+WaveLength      'Calculate wave length
    waitcnt(period)                'to end of wave
    



{{21 Sep 09     Harprit Sandhu 
LCDRoutines4.spin
Propeller Tool Version 1.2.6
Appendix

LCD ROUTINES for a 4 bit data path.     

The following are the names of the methods described in this program

  INITIALIZE_LCD
  PRINT (the_line)
  POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION
  SEND_INSTRUCTION (DISPLAY_CHAR)                      
  SEND_INSTRUCTION2 (DISPLAY_CHAR)
  SEND_CHAR (DISPLAY_CHAR)
  PRINT_DEC (VALUE) | TEST_VALUE
  PRINT_HEX (VALUE, DIGITS)
 
  PRINT_BIN (VALUE, DIGITS)
  CLEAR
  HOME
  SPACE (QTY)

Revisions
  04 Oct 09  Initialize made more robust, misc unnecessary calls removed.
  10 Apr 10  Added 4 lines and eliminated blink on cursor
  
}}
CON                             'all the constants used by all the METHODS
                                'in this program have to be listed here            
  _CLKMODE=XTAL1 + PLL4X        'The system clock spec. 2 X multiplier
  _XINFREQ   = 5_000_000        'ext crystal is 5 Mhz, so 10 Mhz operation
  DataBit4   = 12               'are named so that they can be called by
  DataBit5   = 13               'name if the need ever arises
  DataBit6   = 14               '
  DataBit7   = 15               '                 
  RegSelect  = 16               'The three control lines          
  ReadWrite  = 17               'The three control lines           
  Enable     = 18               'The three control lines
  high       =1                 'define the High state
  low        =0                 'define the Low state  
  Inv_high   =0                 'define the Inverted High state
  Inv_low    =1                 'define the Inverted Low state

VAR                             'these are the variables we will use
   byte  temp                   'for use as a pointer
   byte  index                  'to count characters

PUB Go
  INITIALIZE_LCD
  repeat                             
    position(1,1)
    print(String("Test routine only"))
    position(2,1)
    print(String("4 bit mode line 2"))
    position(3,1) 
    print(String("4 bit mode line 3"))
    position(4,1)
    print(String("4 bit mode line 4"))
    waitcnt(clkfreq/2+cnt)
    clear
    waitcnt(clkfreq/4+cnt)
                                             
PUB INITIALIZE_LCD                'The addresses and data used here are                                                                                                                                                                                          
{{initialize the LCD to use 4 lines of data
Includes the 1/20 second delay, clears the display and positons to 1,1
no variables used}}
  waitcnt(clkfreq/20+cnt)         'specified in the Hitachi data sheet for the
  DIRA[DataBit4..Enable]~~        'display. YOU MUST CHECK THIS FOR YOURSELF.
  SEND_INSTRUCTION (%0011)        'Send 1st
  waitcnt(clkfreq/200+cnt)        'wait                              
  SEND_INSTRUCTION (%0011)        'Send 2nd
  waitcnt(clkfreq/8_000+cnt)      'wait               
  SEND_INSTRUCTION (%0011)        'Send 3rd
  waitcnt(clkfreq/8_000+cnt)      'wait
  SEND_INSTRUCTION (%0010)        'set for 4 bit mode
  waitcnt(clkfreq/8_000+cnt)      'wait
   
  SEND_INSTRUCTION2 (%0010_1000)  'Sets DL=4 bits, N=2 lines, F=5x7 font
  waitcnt(clkfreq/8_000+cnt)      'wait
  SEND_INSTRUCTION2 (%0000_1100)  'Display on, Blink off, Sq Cursor off
  waitcnt(clkfreq/8_000+cnt)      'wait
  SEND_INSTRUCTION2 (%0000_0110)  'Move Cursor, Do not shift display
  waitcnt(clkfreq/8_000+cnt)      'wait
  SEND_INSTRUCTION2 (%0000_0001)  'clears the LCD
  waitcnt(clkfreq/8_000+cnt)      'wait 
  POSITION (1,1)
                                                                        
PUB SEND_INSTRUCTION (D_DATA)        'set up for writing instructions                                                                                                                                    
{{Sends instruction as opposed to a character to the LCD
no variables are used}}                                                      
  CHECK_BUSY                         'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0               'Set up to read busy bit        
  OUTA[RegSelect] := 0               'Set up to read busy bit        
  OUTA[Enable]    := 1               'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit4] := D_DATA 'Ready to READ data in
  OUTA[Enable]    := 0               'Toggle the bit H>L to xfer the data                              
                                                                                          
PUB SEND_INSTRUCTION2 (D_DATA)      'set up for writing instructions                                                                                                                                                            
{{Sends a character to the LCD no variables are used}}        
  CHECK_BUSY                        'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0              'Set up to read busy bit        
  OUTA[RegSelect] := 0              'Set up to read busy bit        
  OUTA[Enable]    := 1              'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit4] := D_DATA>>4   'Ready to READ data in
  OUTA[Enable]    := 0                 'Toggle the bit H>L to xfer the data   
  OUTA[Enable]    := 1                 'Set up to toggle bit H>L
  OUTA[DataBit7..DataBit4] := D_DATA   'Ready to READ data in
  OUTA[Enable]    := 0                 'Toggle the bit H>L to xfer the data
                                                    
PUB SEND_CHAR (D_CHAR)           'set up for writing to the display
{{Sends a single character to the LCD in two halves}}   
  CHECK_BUSY                     'wait for busy bit to clear before sending
  OUTA[ReadWrite] := 0           'Set up to send data
  OUTA[RegSelect] := 1           'Set up to send data
  OUTA[Enable]    := 1           'go high
  OUTA[DataBit7..DataBit4] := D_CHAR>>4  'Send high 4 bits
  OUTA[Enable]    := 0                 'Toggle the bit H>L
  OUTA[Enable]    := 1                 'go high again
  OUTA[DataBit7..DataBit4] :=D_CHAR    'send low 4 bits
  OUTA[Enable]    := 0                 'Toggle the bit H>L
                                                                                              
PUB PRINT (the_line)
{{Print a line of characters to the LCD uses variables index and temp}}
                           'This routine handles more than one Char at a time
                           'called as PRINT(string("the_line"))  
                           ' "the_line" contains the pointer to line. Line is
                           'because we have to point to the line 
                           'zero terminated but we will not use that.  We will
                           'use the string size instead. Easier to understand
  index:=0                 'Reset the counter we are using to count chars sent
  repeat                   'repeat for all chars in the list
    temp:= byte[the_line][index++] 'temp contains the char/byte pointed by index
    SEND_CHAR (temp)               'send the 'pointed to' char to the LCD
  while index<strsize(the_line)    'keep doing it till the last char is sent
                  
PUB POSITION (LINE_NUMBER, HOR_POSITION) | CHAR_LOCATION
{{Position cursor}}  'Line Number : 1 to 4       
  'Horizontal Position : 1 to 20          'specified by the two numbers         
  case LINE_NUMBER                                                             
    1,2:
      CHAR_LOCATION := (LINE_NUMBER-1) * 64   'figure location. See Hitachi HD44780
      CHAR_LOCATION += (HOR_POSITION-1) + 128 'figure location. See Hitachi HD44780
    3:
      CHAR_LOCATION :=148+(HOR_POSITION-1)'for line 3
    4:
      CHAR_LOCATION :=212+(HOR_POSITION-1)'for line 4
  SEND_INSTRUCTION2 (CHAR_LOCATION)       'send the instruction to position cursor
                 
PUB CHECK_BUSY | BUSY_BIT              'routine to check busy bit
{{Check for busy}}
  OUTA[ReadWrite] := 1                 'Set to read the busy bit        
  OUTA[RegSelect] := 0                 'Set to read the busy bit
  DIRA[DataBit7..DataBit4] := %0000    'Set the entire port to be an input        
  REPEAT                          'Keep doing it till clear
    OUTA[Enable]  := 1            'set to 1 to get ready to toggle H>L this bit
    BUSY_BIT := INA[DataBit7]     'the busybit is bit 7 of the byte read
                                  'INA is the 32 input pins on the PROP and we
                                  'are reading data bit 7 which is on pin 15!
    OUTA[Enable]  := 0            'make the enable bit go low for H>L toggle
  WHILE (BUSY_BIT == 1)           'do it as long as the busy bit is 1
  DIRA[DataBit7..DataBit4] := %1111 'done, so set the data port back to outputs  
                                            
PUB PRINT_DEC (VALUE) | TEST_VALUE   'for printing values in decimal format
{{Print a decimal value, whole numbers only}}
  IF (VALUE < 0)                  'if it is a negative value            
    -VALUE                        'change it to a positive
    SEND_CHAR("-")                'and print a - sign on the LCD
  TEST_VALUE := 1_000_000_000     'we get individual digits by comparing to this
                                  'value and then dividing by 10 to get next value
  REPEAT 10                       'There are 10 digits maximum in our system
    IF (VALUE => TEST_VALUE)      'see if our number is bigger than testValue
      SEND_CHAR(VALUE / TEST_VALUE + "0")     'if it is, divide to get the digit
      VALUE //= TEST_VALUE        'figure the next value for the next digit
      RESULT~~                    'result of what just did pass it on below
    ELSEIF (RESULT OR TEST_VALUE == 1) 'if the result was a 1 then div was even
      SEND_CHAR("0")               'so we sent out a zero
    TEST_VALUE /= 10               'we divide by 10 to test for the next digit                                                                                      
                                  
PUB PRINT_HEX (VALUE, DIGITS)     'for printing values in HEX format
{{Print a Hexadecimal value}}
  VALUE <<= (8 - DIGITS) << 2     'you can specify up to 8 digits or FFFFFFFF max
  REPEAT DIGITS                   'do each digit
    SEND_CHAR(LOOKUPZ((VALUE <-= 4) & $F : "0".."9", "A".."F"))
                                  'use lookup table to select character
                                                                      '
PUB PRINT_BIN (VALUE, DIGITS)          'for printing values in BINARY format
{{Print a Binary value}}         
  VALUE <<= 32 - DIGITS                '32 binary digits is the max for our sys
  REPEAT DIGITS                        'Repeat for each digit desired
    SEND_CHAR((VALUE <-= 1) & 1 + "0") 'send a 1 or a 0

{{Clear screen}}   
PUB CLEAR                              'Clear the LCD display and go home
  SEND_INSTRUCTION2 (%0000_0001)       'This is the clear screen and go home command
                                                   
PUB HOME                               'go to position 1,1.
{{Go to position 1,1   Does not clear the screen}}  
  SEND_INSTRUCTION2 (%0000_0011)       'Not cleared
                
PUB SPACE (qty)                        'Prints spaces, for between numbers
{{Print spaces}}
  repeat (qty)
    PRINT(STRING(" "))




{{21 Sep 09    Harprit Sandhu
Utilities.spin
Propeller Tool Ver 1.2.6
Appendix

Program UTILITIES 
  Flash         flashes a pin once, toggles it slowly
  Pause         pause in milliseconds
  GetPotValue   returns PotValue  0-255   
  GetPotValue2  returns PotValue  0-255
  Read3202_0    reads Channel 0 on the 3202, 0-4095
  Read3202_1    reads Channel 1 on the 3202, 0-4095

  Since the pot readers are an important part of
  the utilities, they are read separately
  Using two methods allows you to use two different pot values
  one for each pot.

Potentiometer connections are as follows
3202 connections
   1  Chip select
   2  Pot 1  xxxxxxxxxxxxxxxxx
   3  Pot 2  xxxxxxxxxxxxxxxxx
   4  Ground
   5  Data In
   6  Data out
   7  Clock
   8  5 Volts
Prop connections from 3202 are
  chipSel  = 19           
  chipClk  = chipSel+1  
  chipDout = chipSel+2                                                                                                                                                      
  chipDin  = chipSel+3 

Revisions
21 Sep 09   Set min and max for Pot readings, reduced delay div
            from 2920 to 2900
            Displays both pots and both delays now.
            Using two routines to read the pots allows two pots
            with different values to be set used. Have to be set
            up. Currently they are identical.
            New Xtal changes made.
           
14 Nov 09   Added potvalue2 to read second pot.
            Added ReadChannel,X to read any of 2 channels from
            a MCP 3202

14 Nov 09   Added independent routines to read the two lines of
            A2D on the MCP3202.

18 May 10   Added connections comments above.

Error Reporting:
Please report errors to harprit.sandhu@gmail.com
                  
}}
CON                                                                
  _CLKMODE=XTAL1 + PLL2X         'The system clock spec
  _XINFREQ = 5_000_000           'the oscillator frequency
 
  high     =1
  low      =0
  PotLine  =19  
  PotLine2 =20                                      
  repval   =2                                       
  repval2  =2
  BitsRead =12
  BitsRead2=12
  BitsRead3 =12
  BitsRead4=12     
  chipSel  = 19           
  chipClk  = chipSel+1  
  chipDout = chipSel+2                                                                                                                                                      
  chipDin  = chipSel+3 
  chipSel2  = 23           
  chipClk2  = chipSel2+1  
  chipDout2 = chipSel2+2                                                                                                                                                      
  chipDin2  = chipSel2+3  
 
VAR                                                        
  long  startCnt                                         
  long  startCnt2
  long  endCount  
  long  endCount2
  long  delay     
  long  delay2    
  long  PotValue
  long  PotValue2
  long  ValuTotal
  long  ValuTotal2  
  word  PotReading1 
  word  PotReading2 
  word  PotReading3 
  word  PotReading4 
  word  DataRed

OBJ                              'The methods we will need
  LCD  : "LCDRoutines4"          'for controlling the LCD
 
PUB Go
  LCD.INITIALIZE_LCD              'set up the LCD
  repeat                      
    LCD.POSITION (1,1)            'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot1="))    'Potentiometer position
    LCD.PRINT_DEC(PotReading1)    'print pot value                                                               
    LCD.SPACE(3)                  'erase over old data
     
    LCD.POSITION (2,1)            'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot2="))    'Potentiometer position
    LCD.PRINT_DEC(PotReading2)    'print pot value                                                               
    LCD.SPACE(3)                  'erase over old data
     
    LCD.POSITION (3,1)            'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot3="))    'Potentiometer position
    LCD.PRINT_DEC(PotReading3)    'print pot value                                                               
    LCD.SPACE(3)                  'erase over old data
     
    LCD.POSITION (4,1)            'Go to 1st line 1st space
    LCD.PRINT(STRING("Pot4="))    'Potentiometer position
    LCD.PRINT_DEC(PotReading4)    'print pot value                                                               
    LCD.SPACE(3)                  'erase over old data

    Read3202_0                    'Read Pot routine 
    Read3202_1                    'Read Pot routine2
    Read3202_2                    'Read Pot routine3
    Read3202_3                    'Read Pot routine4
         
PUB FLASH (color)               'routine to flash an LED by color                
    outa[color] :=high          'line that actually sets the LED high
    pause (200)                 'wait till counter reaches this value
    outa[color] :=low           'line that actually sets the LED low
    pause (200)                 'wait till counter reaches this value                                                                                          '
                               
PUB PAUSE(millisecs)            'As set up here it is 1.0 millisecconds
  if millisecs>0
    waitcnt((clkfreq/1_000)*millisecs +cnt)      'ms based on Osc freq

PUB GetPotVal                       
  dira[PotLine]~~                'set potline as output
  valutotal:=0                   'clear total                     
    repeat  repval               'repeat                     
      dira[PotLine]~~            'set potline as output         
      outa[PotLine]~~            'make it high so we can charge the capacitor
      waitcnt(4000+cnt)          'wait for the capacitor to get charged
      dira[PotLine]~             'make potline an input. line switches H>L
      startCnt:=cnt              'read the counter at start of cycle and store
      repeat                     'go into an endless loop                   
      while ina[PotLine]~~       'keep doing it as long as the potline is high
      EndCount := cnt            'read the counter at end of cycle and store
      delay := ((EndCount-StartCnt)-1184)   'calculate time for line to go H>L
      if delay>610_000           'max permitted delay
        delay:=610_000           'clamp delay
      PotValue:=(delay/2000)     'This reduces the value to 0-255 or 1 byte
      valutotal:=valutotal+potvalue    'figures total
      potvalue:=valutotal/repval 'figure average  
      potvalue <#=255
      potvalue #>=0            
  result:=PotValue      'figure average
                                               
PUB GetPotVal2                       
  dira[PotLine2]~~                'set potline as output
  valutotal2:=0                   'clear total                     
    repeat  repval2               'repeat                     
      dira[PotLine2]~~            'set potline as output         
      outa[PotLine2]~~            'make it high so we can charge the capacitor
      waitcnt(4000+cnt)           'wait for the capacitor to get charged
      dira[PotLine2]~             'make potline an input. line switches H>L
      startCnt2:=cnt              'read the counter at start of cycle and store
      repeat                      'go into an endless loop                   
      while ina[PotLine2]~~       'keep doing it as long as the potline is high
      EndCount2 := cnt            'read the counter at end of cycle and store
      delay2:= ((EndCount2-StartCnt2)-1184)   'calculate time for line to go H>L
      if delay2>610_000             'max permitted delay
        delay2:=610_000             'clamp delay
      PotValue2:=(delay2/2300)      'This reduces the value to 0-255 or 1 byte
      valutotal2:=valutotal2+potvalue2    'figures total
      potvalue2:=valutotal2/repval2 'figure average
      potvalue2 <#=255              'clamp at 255
      potvalue2 #>=0                'clamp at 0
      result:=Potvalue2             'use average

PUB Read3202_0                                                                   
  DIRA[chipSel]~~     'osc once to set up 3202                 
  DIRA[chipDin]~~     'data set up to the chip                                    
  DIRA[chipDout]~     'data from the chip to the Propeller     
  DIRA[chipClk]~~     'oscillates to read in data      
    DataRed:=0             'Clear out old data
    outa[chipSel]~~         'Chip select has to be high to start off                       
    outa[chipSel]~          'Go low to start process
                                  
    outa[chipClk]~          'Clock needs to be low to load data    
    outa[chipDin]~~         'must start with Din low to set up 3202                  
    outa[chipClk]~~         'Clock high to read data in
                                  
    outa[chipClk]~          'Low to load     
    outa[chipDin]~~         'High single mode                 
    outa[chipClk]~~         'High to read
                                          
    outa[chipClk]~          'Low to load              
    outa[chipDin]~          'low channel 0         
    outa[chipClk]~~         'High to read
                                   
    outa[chipClk]~          'Low to load      
    outa[chipDin]~~         'msbf high = MSB first               
    outa[chipClk]~~         'High to read
   
    outa[chipDin]~          'making line low for rest of cycle   
    outa[chipClk]~          'Low to load Read the null bit, not stored
    outa[chipClk]~~         'High to read
                    
    repeat BitsRead          'Reads the data into DataRed in 12 steps
      DataRed <<= 1         'Move data by shifting left 1 bit. Ready for next bit
      outa[chipClk]~         'Low to load
      DataRed:=DataRed+ina[chipDout]  'Xfer the data from pin chipDout                          
      outa[chipClk]~~        'High to read                                        
    outa[chipSel]~~          'Put chip to sleep, for low power                     
    PotReading1:=DataRed     'Finished data read for display
    result:=dataRed
   
PUB Read3202_1                       
  DIRA[chipSel]~~     'osc once to set up 3202                 
  DIRA[chipDin]~~     'data set up to the chip                                    
  DIRA[chipDout]~     'data from the chip to the Propeller     
  DIRA[chipClk]~~     'oscillates to read in data                    
    DataRed:=0              'Clear out old data
    outa[chipSel]~~         'Chip select has to be high to start off                       
    outa[chipSel]~          'Go low to start process
                                  
    outa[chipClk]~          'Clock needs to be low to load data    
    outa[chipDin]~~         'must start with Din low to set up 3202                  
    outa[chipClk]~~         'Clock high to read data in
                                  
    outa[chipClk]~          'Low to load     
    outa[chipDin]~~         'High single mode                 
    outa[chipClk]~~         'High to read
                                          
    outa[chipClk]~          'Low to load              
    outa[chipDin]~~         'high channel 1         
    outa[chipClk]~~         'High to read
                                   
    outa[chipClk]~          'Low to load      
    outa[chipDin]~~         'msbf high = MSB first               
    outa[chipClk]~~         'High to read
   
    outa[chipDin]~          'making line low for rest of cycle   
    outa[chipClk]~          'Low to load Read the null bit, not stored
    outa[chipClk]~~         'High to read
  
    repeat BitsRead2         'Reads the data into DataRed in 12 steps
      DataRed <<= 1          'Move data by shifting left 1 bit. Ready for next bit
      outa[chipClk]~         'Low to load
      DataRed:=DataRed+ina[chipDout]  'Xfer the data from pin chipDout                          
      outa[chipClk]~~        'High to read                                        
    outa[chipSel]~~          'Put chip to sleep, for low power                     
    PotReading2:=DataRed     'Finished data read for display
    result:=dataRed
   
PUB Read3202_2                       
  DIRA[chipSel2]~~     'osc once to set up 3202                 
  DIRA[chipDin2]~~     'data set up to the chip                                    
  DIRA[chipDout2]~     'data from the chip to the Propeller     
  DIRA[chipClk2]~~     'oscillates to read in data                    
    DataRed:=0              'Clear out old data
    outa[chipSel2]~~         'Chip select has to be high to start off                       
    outa[chipSel2]~          'Go low to start process
                                  
    outa[chipClk2]~          'Clock needs to be low to load data    
    outa[chipDin2]~~         'must start with Din low to set up 3202                  
    outa[chipClk2]~~         'Clock high to read data in
                                  
    outa[chipClk2]~          'Low to load     
    outa[chipDin2]~~         'High single mode                 
    outa[chipClk2]~~         'High to read
                                          
    outa[chipClk2]~          'Low to load              
    outa[chipDin2]~~         'high channel 0         
    outa[chipClk2]~~         'High to read
                                   
    outa[chipClk2]~          'Low to load      
    outa[chipDin2]~~         'msbf high = MSB first               
    outa[chipClk2]~~         'High to read
   
    outa[chipDin2]~          'making line low for rest of cycle   
    outa[chipClk2]~          'Low to load Read the null bit, not stored
    outa[chipClk2]~~         'High to read
  
    repeat BitsRead3         'Reads the data into DataRed in 12 steps
      DataRed <<= 1          'Move data by shifting left 1 bit. Ready for next bit
      outa[chipClk2]~         'Low to load
      DataRed:=DataRed+ina[chipDout2]  'Xfer the data from pin chipDout                          
      outa[chipClk2]~~        'High to read                                        
    outa[chipSel2]~~          'Put chip to sleep, for low power                     
    PotReading3:=DataRed     'Finished data read for display
    result:=dataRed

PUB Read3202_3                         
  DIRA[chipSel2]~~     'osc once to set up 3202                 
  DIRA[chipDin2]~~     'data set up to the chip                                    
  DIRA[chipDout2]~     'data from the chip to the Propeller     
  DIRA[chipClk2]~~     'oscillates to read in data                    
    DataRed:=0              'Clear out old data
    outa[chipSel2]~~         'Chip select has to be high to start off                       
    outa[chipSel2]~          'Go low to start process
                                  
    outa[chipClk2]~          'Clock needs to be low to load data    
    outa[chipDin2]~~         'must start with Din low to set up 3202                  
    outa[chipClk2]~~         'Clock high to read data in
                                  
    outa[chipClk2]~          'Low to load     
    outa[chipDin2]~~         'High single mode                 
    outa[chipClk2]~~         'High to read
                                          
    outa[chipClk2]~          'Low to load              
    outa[chipDin2]~         'low channel 1         
    outa[chipClk2]~~         'High to read
                                   
    outa[chipClk2]~          'Low to load      
    outa[chipDin2]~~         'msbf high = MSB first               
    outa[chipClk2]~~         'High to read
   
    outa[chipDin2]~          'making line low for rest of cycle   
    outa[chipClk2]~          'Low to load Read the null bit, not stored
    outa[chipClk2]~~         'High to read
  
    repeat BitsRead4         'Reads the data into DataRed in 12 steps
      DataRed <<= 1          'Move data by shifting left 1 bit. Ready for next bit
      outa[chipClk2]~         'Low to load
      DataRed:=DataRed+ina[chipDout2]  'Xfer the data from pin chipDout                          
      outa[chipClk2]~~        'High to read                                        
    outa[chipSel2]~~          'Put chip to sleep, for low power                     
    PotReading4:=DataRed     'Finished data read for display
    result:=dataRed

   













 
EncoderGeek / EncoderGeek   Propeller book programs in order. These programs are also on McGraw Hill Website. Cut and Paste to SPIN.