' {$STAMP BS2}
' {$PBASIC 2.5}
' **************************************************************
' *                        Pongwriter                          *
' *       By Vern Graner SSE, Texas Information Services       *
' **************************************************************
' * Code for writing on Ping Pong Ball with Parallax Serial    *
' * Inkjet printer system *& EFX-TEK Prop-1 BSII board         *
' **************************************************************
' * Created:  V0.1 11-29-2007                                  *
' * Updates: Eric Lunquist- switch text routines               *
' * Updates: Paul Atrkinson - Custom chartacter font test      *
' * Updates: Code cleanup and comments VLG                     *
' **************************************************************

' ************************
' * Conditonal Compile   *
' *************************************************************************
#SELECT $STAMP
  #CASE BS2, BS2E, BS2PE
    T2400       CON     396
    T4800       CON     188
    T9600       CON     84
    T19K2       CON     32
    T38K4       CON     6
  #CASE BS2SX, BS2P
    T2400       CON     1021
    T4800       CON     500
    T9600       CON     240
    T19K2       CON     110
    T38K4       CON     45
  #CASE BS2PX
    T2400       CON     1646
    T4800       CON     813
    T9600       CON     396
    T19K2       CON     188
    T38K4       CON     84
#ENDSELECT

' ************************
' * Idea Cache           *
' *************************************************************************
' Continuous print head motion for "serpentine" printing
' Create a TRG logo font character (Paul)
' Sensor for ball presence b4 printing
' Run hopper conveyor in reverse intermitently for attract mode? (test first)
' Code to print "lucky numbers" or "fortunes" on the ball
' Code to act as "magic 8-ball" for questions

' ************************
' * I/O Definitions      *
' *************************************************************************
  LightPrinter     PIN 0  ' Lights on the indexer tube
  LightIndexer     PIN 1  ' Lights on the print head & pedestal
  LightAgitator    PIN 2  ' Lights on the hopper
  LightTray        PIN 3  ' Lights the holding bin
  Motor            PIN 4  ' hopper conveyor motor
  'avail           PIN 5  '
  'avail           PIN 6  '
  InkJet           PIN 7  ' Serial Inkjet Printer
  ServoIndexer     PIN 8  ' Servo (Normal) - Drops single ball for printing
  ServoPrinthead   PIN 9  ' Servo (Normal) - Positions Print Head
  ServoRotate      PIN 10 ' Servo (Continuous) - Rotates ball for printing
  ServoEject       PIN 11 ' Servo (Normal) - Turns to eject ball
  BallPresent      PIN 12 ' For IR "ball present" sensor
  AltText          PIN 13 ' PULLDOWN Switch - 1= Alt text message select
  ThreeLine        PIN 14 ' PULLDOWN Switch - 1= Three Lines (less ink, faster finish)
  AutoMode         PIN 15 ' PULLDOWN Switch & Button - 1= continuous print

' ************************
' * Constants            *
' *************************************************************************
  Open        CON     $8000        ' Defines "OPEN" serial mode
  Baud        CON     Open + T9600 ' Sets baud rate to combination of speed and mode
  Esc         CON     27           ' standard ASCII code for "escape" character
  Prompt      CON     ">"          ' Inkjet: "Ready" response from inkjet board
  STX         CON     2            ' Inkjet: Signifies "Start of text"
  ETX         CON     3            ' Inkjet: signifies "End of text"
  TRUE        CON     1            ' Used for more "readable" code
  FALSE       CON     0            ' Used for more "readable" code
  StageDelay  CON     500          ' Delay between each lighted section

' ************************
' *Servo Position values *
' ************************
  ServoEjectOut         CON 1100  ' "Eject Ball from pedestal"
  ServoEjectIn          CON 700   ' "Ready to receive ball on pedistal"

  ServoRotateStop       CON 760    ' Continuous rotation servo- STOP
  ServoRotateFwdSlow    CON 785    ' Continuous rotation servo- Fwd Slow
  ServoRotateFwdFast    CON 790    ' Continuous rotation servo- Fwd Fast

  ServoPrintheadTop     CON 1040   ' Move print head to Top of ball
  ServoPrintheadCenter  CON 750    ' Move print head to Equator of ball
  ServoPrintheadBottom  CON 540    ' Move print head to Bottom of ball

  ServoIndexerLoad      CON 825    ' Allow ball into indexer tube
  ServoIndexerRelease   CON 550    ' Release ball from indexer tube

  LineFeed              CON 63     ' Value to increment print head one line
  Speed                 CON 10     ' Print head movement rate

' ************************
' * Data Variables       *
' ************************
  cntI                    VAR Word   ' index counter 1 (0-65,535)
  cntX                    VAR Byte   ' index counter 2 (0-254)
  cntY                    VAR Byte   ' index counter 3 (0-254)
  LineNumber              VAR Word   ' line number position

' ************************
' * Begin Main Program   *
' *************************************************************************
  ProgramBegin:

' ************************
' * Wait for Trigger     *
' ************************
   HIGH  LightTray       ' Light the exit area

   ' While waiting for the button, do some "attract mode" stuff
   ' i.e. sequence the lights
   WaitForTrigger:
   FOR CntY = 0 TO 3      ' Lights are on pins 0-3
     TOGGLE CntY          ' Turn the light ON or OFF
     FOR CntI = 1 TO 250  ' alter to adjust light change speed
       IF AutoMode = TRUE THEN StartSequence 'if trigger, start printing
     NEXT
   NEXT
   GOTO WaitForTrigger

' ************************
' * Printing Being       *
' ************************
  StartSequence:
  HIGH LightAgitator
  HIGH LightPrinter
  HIGH LightIndexer
  HIGH LightTray



' ************************
' * Reset all systems    *
' ************************
  GOSUB SystemInit       ' Reset/initialize all systems

' ************************
' * Run Hopper           *
' ************************
    HIGH LightAgitator  ' Turn on the lights in the hopper
    PAUSE StageDelay    ' Wait a bit (Cosmetic)
    HIGH Motor          ' Turn on the hopper motor

    CntI = 0
    WaitForBall:
    cntI = cntI + 1
    IF CntI = 4096 THEN GOTO HopperEmpty
    IF BallPresent = FALSE THEN WaitForBall
    LOW Motor           ' Turn off the hopper motor
    HIGH LightIndexer   ' Light the indexer area
    PAUSE StageDelay


' ************************
' * Drop a ball          *
' ************************
    LOW LightAgitator   ' Turn off the lights in the hopper
    PAUSE StageDelay

    GOSUB DropBall      ' Drop a new ball into place
    PAUSE StageDelay

' ************************
' * Print the ball       *
' ************************
    PAUSE StageDelay    ' Wait a bit before we continue (cosmetic)
    LOW LightIndexer    ' Turn off light in indexer area

    FOR CntX = 1 TO 3   ' Print 3 lines, 3 times

      IF ThreeLine = TRUE THEN    ' Print 3 lines, 1 time
        FOR CntY = 1 TO 2
          GOSUB PrintHeadLineFeed
        NEXT
      ENDIF

      GOSUB PrintHeadLineFeed
      GOSUB PrintText
      GOSUB RotateBallFwdSlow

      GOSUB PrintHeadLineFeed
      GOSUB Start2
      GOSUB RotateBallFwdSlow

      GOSUB PrintHeadLineFeed
      GOSUB Start3
      GOSUB RotateBallFwdSlow

      IF ThreeLine = TRUE THEN Done_Print

    NEXT

   Done_Print:
   PAUSE 100             ' wait for a bit to make discrete steps
                         ' more visible to observers.
   HIGH LightTray

   GOSUB PrintHeadBottom ' Get the print head out of the way
   PAUSE 100             ' Aesthetics-- Wait for motion to stop

' ************************
' * Eject the ball       *
' ************************
   GOSUB EjectBall       ' Eject the ball
   DEBUG "Done!",CR      ' Cycle finished



GOTO ProgramBegin


END ' Should never get here, but well... :)


'**************************
'* SubRoutines            *
'*******************************************************************

' **************************
' * System Initialization  *
' **************************
  SystemInit:
    PAUSE StageDelay
    LOW LightAgitator   ' Turn off the lights in the hopper
    LOW LightIndexer    ' Turn off the lights on the indexer
    LOW LightPrinter    ' Turn off the lights on the print head
    LOW LightTray       ' Turn off the light in the catch tray

  ' Set linenumber to bottom of ball
  LineNumber = ServoPrintheadBottom

  'Makes sure all servos are in "ready" positions
  FOR cntI = 1 TO 50
    PULSOUT ServoEject, ServoEjectIn
    PULSOUT ServoRotate, ServoRotateStop
    PULSOUT ServoPrinthead, ServoPrintheadBottom
    PULSOUT ServoIndexer, ServoIndexerRelease
    PAUSE 18
  NEXT

  ' Reset InkJet
  SEROUT Inkjet, Baud, [Esc, "C", 25]    ' intercolumn delay values 1-25 (15=1.5 ms)
  SERIN  Inkjet, Baud, 500, No_Inkjet, [WAIT(Prompt)]
  RETURN

  ' Only gets here if the inkjet print board is non-responsive
  No_Inkjet:
  DEBUG "No response from Inkjet board!",CR
  RETURN

' **************************
' * Print Text             *
' **************************
  PrintText:
  '  NOTE: With current ball rotation speed and intercolumn
  '  delay, we get a MAX of 60 characters per line!

  Start:
    ' DEBUG "Line 1",CR
    SEROUT Inkjet, Baud, [STX]
    IF AltText = FALSE THEN
        SEROUT Inkjet, Baud, ["  WWW.THEROBOTGROUP.ORG  <->  The Robot Group Inc.    <->  "]
    ELSE
        SEROUT Inkjet, Baud, ["  HTTP://PLUTOPIA.ORG               WWW.THEROBOTGROUP.ORG!"]
    ENDIF
    SEROUT Inkjet, Baud, [ETX]
    RETURN

  Start2:
  ' DEBUG "Line 2",CR
    SEROUT Inkjet, Baud, [STX]
    IF AltText = FALSE THEN
        SEROUT Inkjet, Baud, ["    Menchaca Elementary School === WHEEL ROUNDUP 2008      "]
    ELSE
        SEROUT Inkjet, Baud, ["    Convergence      Sustainability      Futurism        Art"]
    ENDIF
    SEROUT Inkjet, Baud, [ETX]
    RETURN

  Start3:
    ' DEBUG "Line 3",CR
    SEROUT Inkjet, Baud, [STX]
    IF AltText = FALSE THEN
        SEROUT Inkjet, Baud, ["          The Robot Group 2008      The Ping Pong Printer  "]
    ELSE
        SEROUT Inkjet, Baud, ["  The Robot Group Inc.                       Austin, Texas "]
    ENDIF
    SEROUT Inkjet, Baud, [ETX]
    RETURN

  RETURN

' **************************
' * Rotate Ball            *
' **************************
   RotateBallStop:
   DEBUG "Rotate STOP",CR
   FOR cntI = 1 TO 100 ' Hold in place
     PULSOUT ServoRotate,ServoRotateStop
     PAUSE 20
   NEXT
   RETURN

   RotateBallFwdSlow:
   ' DEBUG "Rotate Slow",CR
   FOR cntI = 1 TO 95 ' Hold in place
     PULSOUT ServoRotate,ServoRotateFwdSlow
     PAUSE 20
   NEXT
   RETURN

   RotateBallFwdFast:
   ' DEBUG "Rotate Fast",CR
   FOR cntI = 1 TO 65 ' Hold in place
     PULSOUT ServoRotate,ServoRotateFwdFast
     PAUSE 20
   NEXT
   RETURN


' **************************
' * Indexer Sequence       *
' **************************
   DropBall:
   'move indexer to allow a ball to enter tube
   FOR cntI = ServoIndexerRelease TO ServoIndexerLoad STEP SPEED
     PULSOUT ServoIndexer,cntI
     PAUSE 20
   NEXT

   FOR cntI = 1 TO 25    ' Hold Position to stop overshoot
     PULSOUT ServoIndexer,ServoIndexerLoad
     PAUSE 20
   NEXT

   HIGH LightPrinter   ' Light the print-head area
'   PAUSE STAGEDELAY

   'move indexer to allow a ball to drop to pedestal
   FOR cntI = ServoIndexerLoad TO ServoIndexerRelease STEP SPEED
     PULSOUT ServoIndexer,cntI
     PAUSE 20
   NEXT

   FOR cntI = 1 TO 10    ' Hold Position to stop overshoot
     PULSOUT ServoIndexer,ServoIndexerRelease
     PAUSE 20
    NEXT

  RETURN


' **************************
' * Print head to Top      *
' **************************
  PrintHeadTop:
   ' DEBUG "Print Head Up",CR
   FOR cntI = ServoPrintHeadBottom TO ServoPrintHeadTop STEP SPEED
     PULSOUT ServoPrinthead,cntI
     PAUSE 20
   NEXT

   FOR cntI = 1 TO 20 ' Hold Position to stop overshoot
     PULSOUT ServoPrinthead,ServoPrintHeadTop
     PAUSE 20
   NEXT

   RETURN


' **************************
' * Print Head Center      *
' **************************
  PrintHeadCenter:
   ' DEBUG "Print Head Center",CR
   FOR cntI = ServoPrintHeadTop TO ServoPrintHeadCenter STEP SPEED
     PULSOUT ServoPrinthead,cntI
     PAUSE 20
   NEXT

   FOR cntI = 1 TO 20 ' Hold Position to stop overshoot
     PULSOUT ServoPrinthead,ServoPrintHeadCenter
     PAUSE 20
   NEXT

   RETURN

' **************************
' * Print Head Bottom      *
' **************************
PrintHeadBottom:
   ' DEBUG "Print Head Bottom",CR
   FOR cntI = ServoPrintHeadTop TO ServoPrintHeadBottom STEP SPEED
     PULSOUT ServoPrinthead,cntI
     PAUSE 20 'servo  pulses need to be separated by 20ms
   NEXT

   FOR cntI = 1 TO 20 ' Hold Position to stop overshoot
     PULSOUT ServoPrinthead,ServoPrintHeadBottom
     PAUSE 20 'servo  pulses need to be separated by 20ms
   NEXT

   RETURN

' **************************
' * Print Head Line Feed   *
' **************************
  PrintHeadLineFeed:
  ' Note: top to bottom is  1050-> 550
  FOR cntI = 1 TO 10
    PULSOUT ServoPrinthead,LineNumber
    PAUSE 20 'servo  pulses need to be separated by 20ms
  NEXT

  ' Could use code here to make sure we don't step printhead too far
  ' Commented out for now- VLG
  'IF LineNumber < 1050 THEN         ' see if we are at last line
  LineNumber = Linenumber + LineFeed ' if not, the n move the head
  'ELSE
  '  GOTO NewBall                    ' if so, then start over again
  'ENDIF
  RETURN


' **************************
' * Eject Ball             *
' **************************
  EjectBall:
  ' DEBUG "Eject ball",CR
  FOR cntI = ServoEjectIn TO ServoEjectOut STEP SPEED
    PULSOUT ServoEject,cntI
    PAUSE 20
  NEXT

  ' DEBUG "Return to Catch",CR
  FOR cntI = ServoEjectOut TO ServoEjectIn STEP SPEED
    PULSOUT ServoEject,cntI
    PAUSE 20
  NEXT

  FOR cntI = 1 TO 25             ' Prevent overshoot
    PULSOUT ServoEject,ServoEjectIn
    PAUSE 20
  NEXT

  RETURN


' **************************
' * Hopper Empty           *
' **************************
  HopperEmpty:
  LOW Motor
  LOW  LightAgitator
  HIGH LightPrinter
  HIGH LightIndexer
  HIGH LightTray


   WaitForTrigger1:
     TOGGLE LightPrinter
     TOGGLE LightIndexer
     TOGGLE LightAgitator
     TOGGLE LightTray

     FOR CntI = 1 TO 100   ' alter to adjust light change speed
       IF AutoMode = FALSE THEN StartSequence 'if trigger, start printing
     NEXT
     GOTO WaitForTrigger1



'**************************
'* Scatchpad Code area    *
'*******************************************************************
' Paul's custom font code
' font data for Robot Group stick man logo
' need to send <ESC><N><ASCII_Code><24 bytes> to set new char,
' SEROUT Inkjet, Baud, [$27,"N",$0,$03, $FC, $04, $02, $04, $42, $08, $45, $09, $49, $0A, $F1, $09, $49, $08, $45, $04, $42, $04, $02, $03, $FC, $00, $00]
' Data is embedded in above string = load new ascii character 0
' DATA  $03, $FC, $04, $02, $04, $42, $08, $45, $09, $49, $0A, $F1, $09, $49, $08, $45, $04, $42, $04, $02, $03, $FC, $00, $00

' then send the ascii code for chr$(0) to make it print
' SEROUT Inkjet, Baud, [$00]