'{$STAMP BS2}
'{$PBASIC 2.5}
' **************************************************************
' *  The "Thereping" a sonar-based Theremin-like Instrument    *
' *  (c) 2005/2006 Vern Graner SSE, Texas Information Services *
' **************************************************************
' * Code for BSII to measure distance on the PING sensor and   *
' * play a corresponding note on the audio out.                *
' **************************************************************
' * Created:  V0.2 11-05-2005                                  *
' **************************************************************

' ************************
' * Pin Assignments      *
' ************************

   Btn1     PIN 0
   Btn2     PIN 1
   Btn3     PIN 2
   PING     PIN 3
   LED1     PIN 4
   SPEAKER  PIN 5
   SYNC     PIN 6
   LED2     PIN 7
   LED3     PIN 8
   LED4     PIN 9




'   LCD     PIN 0    ' Serial LCD panel
'   SPEAKER PIN 1    ' Speaker/Amp
'   PING    PIN 12   ' PING)) Sensor
'   Btn1    PIN 14   ' "Start" button
'   Btn2    PIN 13   ' "Start" button
'   SYNC    PIN 15   ' Sync Pulse

' ********************************
' * Pin Assignments              *
' * BSII PInewood Timer Hardware *
' *************************************************************************
' P0- Servo (Flag)
' p1- "Pulled Up" N.O. pushbutton to gnd (Start)
' P2- "Pulled Down" N.O. pushbutton to V+ (lane 1 sense)
' P3- "Pulled Down" N.O. pushbutton to V+ (lane 2 Sense)
' P4-
' P5-
' P6-
' P7-
' P8-
' P9- Speaker Out
'P10- Red LED
'P11- Yellow LED
'P12- Yellow LED
'P13- Green LED
'P14- Seetron Serial LCD


' ************************
' * Constants            *
' ************************
   N9600     CON $4054 ' LCD Baudmode-9600 bps inverted. Use $40F0 for BS2-SX.
   I         CON 254   ' LCD Instruction prefix value.
   CLR       CON 1     ' LCD clear-screen instruction.
   LINE2     CON 192   ' LCD Address of 1st char of 2nd line.
   TOP       CON 2     ' LCD CRSR to home position
   LOWPos    CON 50   ' Sonar Value for closest note
   HIGHPos   CON 1100   ' Sonar Value for furthest note
   NNotes    CON 14    ' Number of notes to play in the blues scale

' ************************
' * Variables            *
' ************************
   sample     VAR Word  ' time value
   cntI       VAR Byte  ' used in FOR loops
   Duration   VAR Word  ' used to hold MS of time the note is played
   Freq       VAR Word  ' Frequency to play
   Note       VAR Word  ' Note Number (0-7)
   NotePos    VAR Byte  ' Number of division in space above the sensor
   Rest       VAR Word  ' Number of ticks measured on the sync pulse
   NoteTicks  VAR Byte  ' Number of notes to play between sync
   btnWrk     VAR Byte  ' Button Workspace

' ************************
' * Note Table           *
' ************************
' The naming convention for note constants is <note><(s)sharp/(b)flat/(n)atural><octave>
' So, for "C Sharp in the 4th octave" it would be "Cs4".
' Notes are in HZ values (rounded to nearest Hz)
 'C# and Bb and 'D# and Eb are the same in all octaves

   Cn4  CON 262
   Cs4  CON 277 'dup
   Db4  CON 277 'dup
   Dn4  CON 294
   Ds4  CON 311 'dup
   Eb4  CON 311 'dup
   En4  CON 330
   Fn4  CON 349
   Fs4  CON 370 'dup
   Gb4  CON 370 'dup
   Gn4  CON 392
   Gs4  CON 415 'dup
   Ab4  CON 415 'dup
   An4  CON 440
   As4  CON 466 'dup
   Bb4  CON 466 'dup
   Bn4  CON 494

   Cn5  CON 523
   Cs5  CON 554 'dup
   Db5  CON 554 'dup
   Dn5  CON 587
   Ds5  CON 622 'dup
   Eb5  CON 622 'dup
   En5  CON 659
   Fn5  CON 698
   Fs5  CON 740 'dup
   Gb5  CON 740 'dup
   Gn5  CON 784
   Gs5  CON 830 'dup
   Ab5  CON 830 'dup
   An5  CON 880
   As5  CON 932 'dup
   Bb5  CON 932 'dup
   Bn5  CON 988

   Cn6  CON 1047
   Cs6  CON 1109 'dup
   Db6  CON 1109 'dup
   Dn6  CON 1175
   Ds6  CON 1245 'dup
   Eb6  CON 1245 'dup
   En6  CON 1319
   Fn6  CON 1397
   Fs6  CON 1480 'dup
   Gb6  CON 1480 'dup
   Gn6  CON 1568
   Gs6  CON 1661 'dup
   Ab6  CON 1661 'dup
   An6  CON 1760
   As6  CON 1865 'dup
   Bb6  CON 1865 'dup
   Bn6  CON 1976

   Cn7  CON 2093
   Cs7  CON 2217 'dup
   Db7  CON 2217 'dup
   Dn7  CON 2349
   Ds7  CON 2489 'dup
   Eb7  CON 2489 'dup
   En7  CON 2637
   Fn7  CON 2794
   Fs7  CON 2960 'dup
   Gb7  CON 2960 'dup
   Gn7  CON 3136
   Gs7  CON 3322 'dup
   Ab7  CON 3322 'dup
   An7  CON 3520
   As7  CON 3729 'dup
   Bb7  CON 3729 'dup
   Bn7  CON 3951

   Cn8  CON 4186

' ************************
' * Initialize           *
' ************************
   Clock     CON 240   ' The clock frequency in MS from rise to fall of SQ wave
   OffSet    CON 10
   Notepos = (HighPos - LowPos) / NNotes ' Determine how many discrete positions
                                         ' above the sensor there should be
   cntI = 0
HIGH LED3
HIGH LED2
' ************************
' * Main Code            *
' *************************************************************************

SyncWait:
BUTTON SYNC, 1, 255, 0, BtnWrk, 0, SyncWait ' Wait for a sync pulse
AROUND:                 ' Loop return point

TOGGLE LED1
'TOGGLE LED2
'TOGGLE LED3
'TOGGLE LED4


DO WHILE BTN1=0  ' Check for "drone" button and play drone sound if pressed
  LOW LED2
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED2

  LOW LED3
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED3

  LOW LED1
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED1

  LOW LED4
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED4

  LOW LED1
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED1

  LOW LED3
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED3

  LOW LED2
  Duration = Clock
  FREQOUT Speaker,Duration,Cn4/2, Cn4 'Actually play the note!
  PAUSE offset
  HIGH LED2

  LOW LED1
    Duration = Clock
  FREQOUT Speaker,(Duration-10),As4/4, As4/2 'Actually play the note!
  HIGH LED1

  SyncWait2:
  BUTTON SYNC, 1, 255, 0, BtnWrk, 0, SyncWait2 ' Wait for a sync pulse


  LOOP

cntI=1                'Set number of notes per clock pulse to 1 (1/4 notes)
Duration = Clock *2

IF btn2 = 0 THEN
  cntI = 2           'Set number of notes per clock pulse to 2 (1/8 notes)
  Duration = Clock   'Set 1/8 note duration
'  LOW LED4
'  HIGH LED2
ENDIF

IF btn3 = 0 THEN
  cntI = 4           'Set number of notes per clock pulse to 4 (1/16 notes)
  Duration = Clock/2 'Set 1/8 note duration note: timing is getting tricky,
'  LOW LED2
'  HIGH LED4
ENDIF

FreePlay:

PULSOUT PING, 5         ' Send a ping to check hand position
PULSIN  PING, 1, Sample ' read the return time and store it in "Sample1"

IF Sample > HighPos THEN SyncWait ' Don't play if the hand is not present

' This line pics the note based on the sensed hand position
Note = (SAMPLE - LowPos) / NotePos

' C blues scale      C - Eb - F - Gb - G - Bb - C
' Pitch DEcreases as distance decreases
'LOOKUP NOTE, [Bb5, Cn6, Eb6, Fn6, Gb6, Gn6, Bb6, Cn7, Eb7, Fn7, Gb7, Gn7, Bb7, Cn8], FREQ

' Pitch INcreases as distance decreases - More "Theremin-like"
LOOKUP NOTE, [Cn8, Bb7, Gn7, Gb7, Fn7, Eb7, Cn7, Bb6, Gn6, Gb6, Fn6, Eb6, Cn6, Bb5], FREQ

LOW CntI+6   'LED light sequence

PlayNote:
FREQOUT Speaker,Duration-5,Freq, (freq/4)-5 'play note and 2 octaves down minus 5 hz for chorusing
'PAUSE offset +5
HIGH CntI+6       'LED light sequence
cntI = cntI - 1

IF cntI > 0 THEN FreePlay

GOTO SyncWait


' ************************
' * Reference Section    *
' **************************************************************
'Notes:

'Another cool website:
'http://www.phy.mtu.edu/~suits/notefreqs.html

' From this web site:
' http://www.jazclass.aust.com/scales/scablu.htm
'   1. C Blues scale
'     C - Eb - F - Gb - G - Bb - C

'   2. G Blues scale
'      G - Bb - C - Db - D - F - G

'   3. D Blues scale (Down - Up - Top)
'      D - F - G - Ab - A - C - D

'   4. A Blues scale
'    A - C - D - Eb - E - G - A

'   5. E Blues scale
'     E - G - A - Bb - B - D - E

'   6. B Blues scale (Down - Up - Top)
'     B - D - E - F - F# - A - B

'   7. F# AND Gb Blues scales
'      F# - A - B - C - C# - E - F#
'      Gb - A - B - C - Db - E - Gb

'   8. Db AND C# Blues scales
'     Db - E - Gb - G - Ab - B - Db
'     C# - E - F# - G - G# - B - C#

'   9. Ab Blues scale (Down - Up - Top)
'      Ab - B - Db - D - Eb - Gb - Ab

'  10. Eb Blues scale
'      Eb - Gb - Ab - A - Bb - Db - Eb

'  11. Bb Blues scale
'      Bb - Db - Eb - E - F - Ab - Bb

'  12. F Blues scale (  Down - Up - Top)
'      F - Ab - Bb - B - C - Eb - F