Linux Format forums Forum Index Linux Format forums
Help, discussion, magazine feedback and more
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

OK, now the start of the audio scope...
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    Linux Format forums Forum Index -> Programming
View previous topic :: View next topic  
Author Message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Wed Mar 27, 2013 10:46 pm    Post subject: Reply with quote

This is getting to be a serious tool now guys...

For the time being everything is saved and loaded to the /tmp drawer...

READ THE CODE for more information...

It has auto-save and load of a user config now and pseudo vertical shift. It has commented out means of generating a test audio sinewave at 1KHz...

The SOX version will need a change of absolute address for it to work. Presently working on SYNC/TRIGGER methods and drawing the plots together... Then the really hard bit starts...

Remember, that this is being _built_ on a Macbook Pro 13 inch with only ONE mic input...

I might add that this site is probably the best, and, least draconian that I am a member of. Well done ADMINs and Moderators you are doing a good job...

Enjoy...

Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested on both in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
version="           \$VER: AudioScope.sh_Version_0.00.33_PD_B.Walker_G0LCU.           "
setup=$version
demo=0
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables.
count=0
number=0
char="?"
vert=12
vert_shift=2
vshift="?"
horiz=9
kbinput="?"
graticule="Public Domain, 2013, B.Walker, G0LCU."
kbinput="RUN"
tbinput=1
strlen=1
# "grab" is for future usage and reserved.
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=1
# Scan retraces...
scan=1
scanloops=1
# Timebase variables...
subscript=0
# scan_start is from 0 to ( length of file - 64 )...
scan_start=0
# scan_jump is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# scan_finish is not used yet...
scan_end=1935

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=0\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=0\n" >> /tmp/AudioScope.config
   printf "scanloops=1\n" >> /tmp/AudioScope.config
   printf "scan_start=0\n" >> /tmp/AudioScope.config
   printf "scan_jump=1\n" >> /tmp/AudioScope.config
   printf "scan_end=1935\n" >> /tmp/AudioScope.config
   printf "setup='$version'\n" >> /tmp/AudioScope.config
fi

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set colours for plot.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to store the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 2000 bytes of random data. This may be slow on some older machines...
   if [ $demo -eq 0 ]
   then
      char=""
      for count in {0..1999}
      do
         number=$[ ( $RANDOM % ( 256 ) ) ]
         char=`printf '\\\\x'"%02x" $number`
         printf "$char" >> /tmp/waveform.raw
      done
      sleep 0.1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # The real "vert" value stored into "grab" for future use.
      grab=$vert
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # IMPORTANT! The display must be inverted because of the way a terminal plots its characters...
      vert=$[ ( 19 - $vert ) ]
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# this is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      printf "\x1B[23;3f$version"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# This line is no longer used:- kbinput=`printf "$kbinput" | tr [:lower:] [:upper:]`
kbcommands()
{
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
   fi
   # Run scans in captured mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
   fi
   # Swtich off capture mode and rerun one storage shot only
   if [ "$kbinput" == "HOLD" ]
   then
      status=2
      hold=0
      scanloops=1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default.
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scanloops=10
      scan_end=1935
      demo=0
      hold=1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      strlen=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      strlen=$[ ( $strlen - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $strlen )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      strlen=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      strlen=$[ ( $strlen - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $strlen )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=2
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=25
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         # RUN<CR> will re-enable it if required.
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( $vert_shift - 2 ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   statusline
   sleep 1
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .................................. Switch capture to default DEMO mode.\n"
   printf "DSP<CR> ................................. Switch capture to Linux /dev/dsp mode.\n"
   printf "SOX<CR> .................. Switch capture to multi-platform SOund eXchange mode.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ................................... Sets the number of scans to 100.\n"
   printf "VER<CR> ................. Displays the version number inside the status windows.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> ............ (Not available in DEMO mode.) Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ............. (Inaccurate in DEMO mode.) Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
   sleep 1
}

# #########################################################
# Do an initial screen set up...
display
statusline

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   sleep 0.1
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The first extremely simple construction part.
# Photos will be upload somewhere very soon...
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# #########################################################

[/code]
_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Mon Apr 01, 2013 9:51 pm    Post subject: Reply with quote

The command DRAW facility is now finished. The attached image is a whistle into the Macbook Pro microphone with the Timebase TBVAR command set to tart 10 bytes in with a jump of 3 bytes.

I.E. the TB set to 10 along and the same as 500uS/DIV...

The next upload will be sorting out the Pseudo-sync/Trigger and may take a while as I am in the middle of a simple vertical calibrator using the sinewave generator at the start of the script.

This is now functional and entirely in very basic shell concepts...

Enjoy...



Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested on both in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.36_PD_B.Walker_G0LCU.           "
setup=$version
demo=0
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables.
count=0
number=0
char="?"
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
horiz=9
graticule="Public Domain, 2013, B.Walker, G0LCU."
kbinput="?"
tbinput=1
str_len=1
# "grab" is for future usage and reserved.
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=1
# Scan retraces...
scan=1
scanloops=1
# Timebase variables...
subscript=0
# scan_start is from 0 to ( length of file - 64 )...
scan_start=0
# scan_jump is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# scan_finish is not used yet...
scan_end=1935

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=0\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=0\n" >> /tmp/AudioScope.config
   printf "scanloops=1\n" >> /tmp/AudioScope.config
   printf "scan_start=0\n" >> /tmp/AudioScope.config
   printf "scan_jump=1\n" >> /tmp/AudioScope.config
   printf "scan_end=1935\n" >> /tmp/AudioScope.config
   printf "vert_shift=2\n" >> /tmp/AudioScope.config
   printf "setup='$version'\n" >> /tmp/AudioScope.config
fi

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to store the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 2000 bytes of random data. This may be slow on some older machines...
   if [ $demo -eq 0 ]
   then
      char=""
      for count in {0..1999}
      do
         number=$[ ( $RANDOM % ( 256 ) ) ]
         char=`printf '\\\\x'"%02x" $number`
         printf "$char" >> /tmp/waveform.raw
      done
      sleep 0.1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # The real "vert" value stored into "grab" for future use.
      grab=$vert
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # IMPORTANT! The display must be inverted because of the way a terminal plots its characters...
      vert=$[ ( 19 - $vert ) ]
      # Generate a smple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points in non-capture mode ONLY.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section is needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi

      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
   read -p "Press <CR> to continue:- " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                               "
   status=1
   statusline   
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan, please wait..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      printf "\x1B[23;3f$version"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
   : # NOP
}

# #########################################################
# this is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      printf "\x1B[23;3f$version"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# This line is no longer used:- kbinput=`printf "$kbinput" | tr [:lower:] [:upper:]`
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
   fi
   # Run scans in captured mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
   fi
   # Swtich off capture mode and rerun one storage shot only
   if [ "$kbinput" == "HOLD" ]
   then
      status=2
      hold=0
      scanloops=1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default.
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scanloops=10
      scan_end=1935
      demo=0
      hold=1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=2
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=25
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         # RUN<CR> will re-enable it if required.
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( $vert_shift - 2 ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      status=3
      hold=0
      scanloops=1
      draw
   fi
   # ************* Connected plots done. *************
   statusline
   sleep 1
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .................................. Switch capture to default DEMO mode.\n"
   printf "DSP<CR> ................................. Switch capture to Linux /dev/dsp mode.\n"
   printf "SOX<CR> .................. Switch capture to multi-platform SOund eXchange mode.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ................................... Sets the number of scans to 100.\n"
   printf "VER<CR> ................. Displays the version number inside the status windows.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> ............ (Not available in DEMO mode.) Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ............. (Inaccurate in DEMO mode.) Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
   sleep 1
}

# #########################################################
# Do an initial screen set up...
display
statusline

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   sleep 0.1
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The first extremely simple construction part.
# Photos will be upload somewhere very soon...
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
guy
LXF regular


Joined: Thu Apr 07, 2005 1:07 pm
Posts: 1069
Location: Worcestershire

PostPosted: Tue Apr 02, 2013 1:42 pm    Post subject: Reply with quote

That is one truly awesome shell script. Cool

How about adding an FFT to display real-time frequency spectra? Razz

More seriously, could it divide usefully into separate I/O, Control and Display scripts? I'm thinking that might make it easier to add new input sources and display/output modes - and control functions too. For example your SOX and dsp inputs seem to share a lot of code; you could define an "abstracted" input interface between scripts, then have individual device driver scripts for each input type. No pressure. Wink
_________________
Cheers,
Guy
The eternal help vampire
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Tue Apr 02, 2013 3:26 pm    Post subject: Reply with quote

Hi guy...
(Apologies for typos...)

> That is one truly awesome shell script.

Thank you sir, I take that as a compliment... ;o)

> How about adding an FFT to display real-time frequency spectra?

Ha ha, If I was clever enough I would... ;oD

> More seriously, could it divide usefully into separate I/O, Control and Display scripts?

Quite possibly, but remember EVERTHING including basic test circuits HAVE to be included inside the one script and these separate callable scripts would have to generated like the 1KHz signal generator(s).

This could make the script hundreds of KB in size. I have no idea if there is a maximum limit of a script size in a bash terminal.

> I'm thinking that might make it easier to add new input sources and display/output modes - and control functions too. For example your SOX and dsp inputs seem to share a lot of code; you could define an "abstracted" input interface between scripts, then have individual device driver scripts for each input type. No pressure.

Gimme chance... ;oD Nice idea(s), my biggest problem is detecting, getting and determining the DC component into a Macbook Pro which only has ONE audio input... I have worked out how the switch the input through the script from AC to DC but have yet to prove it. Remember ICs are NOT allowed, only FETs and Bipolars, and stripboard for PCBs - simple enough that each stage can be built by kids...

Still working out how to get DC in on ONE input only...

I have a simple method of relay switching AC to DC and back using the 1KHz generator but even with a chopper I have no means, AFAIK, whether the DC is +ve or -ve.

This is the idea I have gotten, use a chopper to get the relative DC level, and on exactly the same multivib use a VFO section to detect whether the signal is +ve or -ve, a low freq being -ve and a high freq being +ve... FM and AM in 1 swoop... ;oD

Remember I have only ONE input...

The code should be easy...

The mic-ear photos that pertain to the end of the script:-






Bazza...
_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Sun Apr 07, 2013 10:23 am    Post subject: Reply with quote

The DRAW command now works immediately after a REAL scan...
(On the first run it defaults to OFF for slow machines.)
It can be turned off using the HOLD command...

http://wisecracker.host22.com/public/cal_plot.jpg

http://wisecracker.host22.com/public/cal_draw.jpg

The two images are the SOX sinewave generator auto-running from
the script with the earphone output connected to the mic input using the home
built hardware previously shown and the levels set using the output volume
and mic input controls.

The TBVAR set at 3 in and 3 jump for easy viewing, equvalent to 500uS/DIV,
proving the horizontal calibration is correct, 2 divisions per cycle...

Set to 1mS/DIV and you will see the calibrtaion is correct.

EDIT: Just removed a copy and paste error by me. It does not affect the
program at all...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested on both in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.38_PD_B.Walker_G0LCU.           "
setup=$version
demo=0
drawline=0
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables.
count=0
number=0
char="?"
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
horiz=9
graticule="Public Domain, 2013, B.Walker, G0LCU."
kbinput="?"
tbinput=1
str_len=1
# "grab" is for future usage and reserved.
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=1
# Scan retraces...
scan=1
scanloops=1
# Timebase variables...
subscript=0
# scan_start is from 0 to ( length of file - 64 )...
scan_start=0
# scan_jump is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# scan_finish is not used yet...
scan_end=1935

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to store the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 2000 bytes of random data. This may be slow on some older machines...
   if [ $demo -eq 0 ]
   then
      char=""
      for count in {0..1999}
      do
         number=$[ ( $RANDOM % ( 256 ) ) ]
         char=`printf '\\\\x'"%02x" $number`
         printf "$char" >> /tmp/waveform.raw
      done
      sleep 0.1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # The real "vert" value stored into "grab" for future use.
      grab=$vert
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # IMPORTANT! The display must be inverted because of the way a terminal plots its characters...
      vert=$[ ( 19 - $vert ) ]
      # Generate a smple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   if [ $drawline -eq 1 ]
   then
      draw
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points in non-capture mode ONLY.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section is needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi

      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
   status=1
   statusline   
}

# #########################################################
# this is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      printf "\x1B[23;3f$version"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# This line is no longer used:- kbinput=`printf "$kbinput" | tr [:lower:] [:upper:]`
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
   fi
   # Run scans in captured mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
   fi
   # Swtich off capture mode and rerun one storage shot only
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default.
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scanloops=10
      scan_end=1935
      demo=0
      hold=1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=2
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=25
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         # RUN<CR> will re-enable it if required.
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( $vert_shift - 2 ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      draw
   fi
   # ************* Connected plots done. *************
   statusline
   sleep 1
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .................................. Switch capture to default DEMO mode.\n"
   printf "DSP<CR> ................................. Switch capture to Linux /dev/dsp mode.\n"
   printf "SOX<CR> .................. Switch capture to multi-platform SOund eXchange mode.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ................................... Sets the number of scans to 100.\n"
   printf "VER<CR> ................. Displays the version number inside the status windows.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> ............ (Not available in DEMO mode.) Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ............. (Inaccurate in DEMO mode.) Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
   sleep 1
}

# #########################################################
# Do an initial screen set up...
display
statusline

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   user_config
   sleep 0.1
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The first extremely simple construction part.
# Photos will be upload somewhere very soon...
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Mon Apr 08, 2013 7:07 pm    Post subject: Reply with quote

This upload now has all the deliberate slowing down "sleep 1" lines removed and placed into the correct positions and a general cleanup.

It is also here and has been voted 5 stars, I am gobsmacked:-

http://www.unix.com/shell-programming-scripting/212939-start-simple-audio-scope-shell-script.html

The start of the internal synchronisation code is started and an auto-save facility added.

This auto-save is _volatile_ so use with caution. By volatile I mean, when enabled it WILL save a copy of EVERY scan whether it is a capture or a replay.

It is easy to code for capture only but I decided to do every scan because it is easier to delete files than try to get them back again. The filemanes are _numeric_ using EPOCH values and saved to /tmp ATM...

The new commands are SAVEON, SAVEOFF, TIRG with unfinished subcommands of SYNCEQ, SYNCGT and SYNCLT. I am working on these in the evenings, UK local time and should be ready by the weekend.
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested on both in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.50_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
demo=0
drawline=0
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables.
count=0
number=0
char="?"
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
horiz=9
graticule="Public Domain, 2013, B.Walker, G0LCU."
kbinput="?"
tbinput=1
str_len=1
# "grab" is for future usage and reserved.
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=1
# Scan retraces...
scan=1
scanloops=1
# Timebase variables...
subscript=0
# scan_start is from 0 to ( length of file - 64 )...
scan_start=0
# scan_jump is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# scan_finish is not used yet...
scan_end=1935
# Synchronisation variavles...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 0 and 255 of the REAL grab(s)...
sync_point=128

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to store the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 2000 bytes of random data. This may be slow on some older machines...
   if [ $demo -eq 0 ]
   then
      char=""
      for count in {0..1999}
      do
         number=$[ ( $RANDOM % ( 256 ) ) ]
         char=`printf '\\\\x'"%02x" $number`
         printf "$char" >> /tmp/waveform.raw
      done
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # The real "vert" value stored into "grab" for future use.
      grab=$vert
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # IMPORTANT! The display must be inverted because of the way a terminal plots its characters...
      vert=$[ ( 19 - $vert ) ]
      # Generate a smple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points in non-capture mode ONLY.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section is needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi

      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# this is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion enabled and set to $sync_point..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# This line is no longer used:- kbinput=`printf "$kbinput" | tr [:lower:] [:upper:]`
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default.
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scanloops=10
      scan_end=1935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=2
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=25
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         # RUN<CR> will re-enable it if required.
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( $vert_shift - 2 ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and ptriggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise="OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=0
      scan_jump=1
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger range:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         status=4
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         status=4
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         status=4
      fi
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      save_string="OFF"
   fi
   # *********** Auto-saving facility end. ***********
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> ............ (Not available in DEMO mode.) Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ............. (Inaccurate in DEMO mode.) Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "TRIG<CR> ............. Sets the synchronisation point for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ ......................................... Unfinished.\n"
   printf "        SubCommand: SYNCGT ......................................... Unfinished.\n"
   printf "        SubCommand: SYNCLT ......................................... Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   user_config
   sleep 0.1
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The first extremely simple construction part.
# Photos will be upload somewhere very soon...
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Sun Apr 14, 2013 3:17 pm    Post subject: Reply with quote

A few updates along with a pointer inside the builtin help file to a Manual:-

http://wisecracker.host22.com/public/AudioScope_Manual.readme

This Manual includes the first construction stage.
It is NOT finished but fully enough for the present stage(s)...

The pseudo trigger and sync modes should be ready by the week end...

I HAVE found a bug, and will be cured for the next version...
I suspect no one who has tried this will find it however...

Writing manuals takes hours...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested on both in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.55_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
demo=0
drawline=0
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables.
count=0
number=0
char="?"
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
horiz=9
graticule="Public Domain, 2013, B.Walker, G0LCU."
kbinput="?"
tbinput=1
str_len=1
# "grab" is for future usage and reserved.
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=1
# Scan retraces...
scan=1
scanloops=1
# Timebase variables...
subscript=0
# scan_start is from 0 to ( length of file - 64 )...
scan_start=0
# scan_jump is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# scan_finish is not used yet...
scan_end=1935
# Synchronisation variavles...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 0 and 255 of the REAL grab(s)...
sync_point=128

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to store the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 2000 bytes of random data. This may be slow on some older machines...
   if [ $demo -eq 0 ]
   then
      char=""
      for count in {0..1999}
      do
         number=$[ ( $RANDOM % ( 256 ) ) ]
         char=`printf '\\\\x'"%02x" $number`
         printf "$char" >> /tmp/waveform.raw
      done
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # The real "vert" value stored into "grab" for future use.
      grab=$vert
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # IMPORTANT! The display must be inverted because of the way a terminal plots its characters...
      vert=$[ ( 19 - $vert ) ]
      # Generate a smple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points in non-capture mode ONLY.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section is needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi

      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# this is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion enabled and set to $sync_point..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# This line is no longer used:- kbinput=`printf "$kbinput" | tr [:lower:] [:upper:]`
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default.
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scanloops=10
      scan_end=1935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=2
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=25
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         # RUN<CR> will re-enable it if required.
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( $vert_shift - 2 ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and ptriggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise="OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=0
      scan_jump=1
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger range:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         status=4
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         status=4
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         status=4
      fi
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> ............ (Not available in DEMO mode.) Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ............. (Inaccurate in DEMO mode.) Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "TRIG<CR> ............. Sets the synchronisation point for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ ......................................... Unfinished.\n"
   printf "        SubCommand: SYNCGT ......................................... Unfinished.\n"
   printf "        SubCommand: SYNCLT ......................................... Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "\nManual here:  < http://wisecracker.host22.com/public/AudioScope_Manual.readme > \n\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# Photos will be upload somewhere very soon...
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
guy
LXF regular


Joined: Thu Apr 07, 2005 1:07 pm
Posts: 1069
Location: Worcestershire

PostPosted: Sun Apr 14, 2013 5:58 pm    Post subject: Reply with quote

Bazza wrote:
Writing manuals takes hours...

Some of us do it for a living. Razz
_________________
Cheers,
Guy
The eternal help vampire
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Thu May 02, 2013 7:32 pm    Post subject: Reply with quote

Found 2 bugs and 1 programming error, yup there are bugs... ;oO
The bugs are esoteric but the error is stupidity on my part... ;oD

I suspect none have been found by yourselves who are trying this out however...

Removed the bash RANDOM call and used /dev/urandom instead. It is _infinitely_ quicker for the DEMO capture mode...

The first of the _internal_sync_ routines done.
Help file updated, etc, etc...

From Command mode:-

TRIG<CR>
SYNCEQ<CR>
Caps shift u or caps shift d to decide a sync point from 15 to 240. Then <CR>...
This starts the display from the value set.
Do all this again and the trace will start from another point with the value chosen...
If the value is not found then the trace runs from the start of the waveform.raw file at the FASTEST timebase speed...

Working on negative going SYNCLT and positive going SYNCGT ATM...

The code has now had extensive testing on an ACER Aspire One netbook using PCLinuxOS 2009 in DEMO and DSP modes also...

Before running delete your existing /default/full/path/to/AudioScope.config file so that the
changes can take place correctly... Also manually change the zero_offset value to give a centre straight line with 0 input voltage. It is now -2 on my Macbook Pro machine...

(Also uploaded to http://www.unix.com/ )

Feedback would be welcome, TIA...

Enjoy...

Bazza...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested on both in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.68_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
# Default first time run capture mode, 0 = DEMO.
demo=0
# Draw proceedure mode, 0 = OFF
drawline=0
# Pseudo-continuous data file saving.
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables...
count=0
number=0
char="?"
# Vertical components...
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
# Display setup...
graticule="Public Domain, 2013, B.Walker, G0LCU."
# Keyboard components...
kbinput="?"
tbinput=1
# "str_len" is a reusable variable IF required...
str_len=1
# "grab" is used for internal pseudo-synchronisation...
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=-2
# Horizontal components...
horiz=9
# Scan retraces...
scan=1
scanloops=1
# Timebase variable components...
subscript=0
# "scan_start" is from 0 to ( length of file - 64 )...
scan_start=0
# "scan_jump" is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# "scan_end" is at least 64 bytes in from the absolute file end...
scan_end=47935
# Synchronisation variavles...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 15 and 240 of the REAL grab(s)...
sync_point=128
sync_input="?"

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to capture, (and store), the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 48000 bytes of random data.
   if [ $demo -eq 0 ]
   then
      # Use "sleep" to simulate a 1 second burst.
      sleep 1
      # "/dev/urandom is now used instead of RANDOM as it is MUCH faster.
      dd if=/dev/urandom of=/tmp/waveform.raw bs=48000 count=1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   # Now tested on PCLinuxOS 2009 and Debian 6.0.x.
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # Generate a smple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points.
# Defaults to OFF on the very first time run.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section _is_ needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi

      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion set to $sync_point$synchronise..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only, this disables the DRAW command.
   # Use DRAW to re-enable again. This is deliberate for slow machines...
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default, but with 10 sweeps...
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=10
      scan_end=47935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x and now PCLinuxOS 2009...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=6
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=60
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=600
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( 2 - $vert_shift ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and ptriggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise=" and OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=$[ ( $scan_start + 1 ) ]
      scan_jump=1
      scanloops=1
      subscript=$scan_start
      grab=0
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=0
         break
      fi
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger type, <CR> to disable:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         synchronise=", ON and fixed"
         trigger
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -eq $sync_point ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         synchronise=", ON and positive going"
         trigger
         : # NOP... Place holder only.
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         synchronise=", ON and negative going"
         trigger
         : # NOP... Place holder only...
      fi
      if [ "$kbinput" == "EXT" ]
      then
         # Remember Corona688's code from the early stages of this thread...
         synchronise=", EXTERNAL and waiting"
         : # NOP... Place holder only,
      fi
      status=4
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> .......................................... Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ........................................ Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "TRIG<CR> ........... Sets the synchronisation methods for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ ........ Set the internal SYNC to a fixed value only.\n"
   printf "        SubCommand: SYNCGT ......................................... Unfinished.\n"
   printf "        SubCommand: SYNCLT ......................................... Unfinished.\n"
   printf "        SubCommand: EXT ............................................ Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "\n"
   printf "Manual here: <  http://wisecracker.host22.com/public/AudioScope_Manual.readme  >\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# This is the active part of the pseudo-synchroisation section.
trigger()
{
   while true
   do
      printf "\x1B[0;37;40m\x1B[20;14f"
      # This input method is something akin to BASIC's INKEY$...
      read -p "Sync point:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s sync_input
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$sync_input" == "" ]
      then
         break
      fi
      if [ "$sync_input" == "U" ]
      then
         sync_point=$[ ( $sync_point + 1 ) ]
      fi
      if [ "$sync_input" == "D" ]
      then
         sync_point=$[ ( $sync_point - 1 ) ]
      # Ensure the synchronisation point is NOT out of bounds.
      fi
      if [ $sync_point -ge 240 ]
      then
         sync_point=240
      fi
      if [ $sync_point -le 15 ]
      then
         sync_point=15
      fi
      printf "\x1B[23;3f Synchronisation point set to $sync_point...                                        "
   done
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# Photos will be upload somewhere very soon...
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Sun Jun 23, 2013 2:21 pm    Post subject: Reply with quote

Well the positive going and negative going sync is done although IMHO they are not of much use.

The EXT trigger is on hold until a calibrated Y amp, at least AC coupled, is finished. A starter piece of home brew hardware is under construction.

I am now working on a low signal level ZOOM facility.

This is for signal levels that are actually inside 4 bits of depth instead of the quantised 4 bit depth used for the actual display of large signals inside the terminal window...

Also the simple Y amp and vertical calibration circuits to be added to the end of the script too.
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Also to others on the same site for their input too.
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested in /dev/dsp mode on an Acer Aspire One netbook booting from a USB stick running PCLinuxOS 2009; also with
# the /dev/dsp sinewave generator enabled.
# Tested on all three in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# Relevant pointers to help:-
# http://wisecracker.host22.com/public/AudioScope_Manual.readme
# http://wisecracker.host22.com/public/cal_draw.jpg
# http://wisecracker.host22.com/public/cal_plot.jpg
# http://wisecracker.host22.com/public/mic_ear1.jpg
# http://wisecracker.host22.com/public/mic_ear2.jpg
# http://wisecracker.host22.com/public/mic_ear3.jpg
# http://wisecracker.host22.com/public/mic_ear4.jpg
#
# The latest vesrion will always be here:-
# http://www.unix.com/shell-programming-scripting/212939-start-simple-audio-scope-shell-script.html
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.80_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
# Default first time run capture mode, 0 = DEMO.
demo=0
# Draw proceedure mode, 0 = OFF
drawline=0
# Pseudo-continuous data file saving.
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables...
count=0
number=0
char="?"
# Vertical components...
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
# Display setup...
graticule="Public Domain, 2013, B.Walker, G0LCU."
# Keyboard components...
kbinput="?"
tbinput=1
# "str_len" is a reusable variable IF required...
str_len=1
# "grab" is used for internal pseudo-synchronisation...
grab=0
# "zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
zero_offset=-2
# Horizontal components...
horiz=9
# Scan retraces...
scan=1
scanloops=1
# Timebase variable components...
subscript=0
# "scan_start" is from 0 to ( length of file - 64 )...
scan_start=0
# "scan_jump" is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# "scan_end" is at least 64 bytes in from the absolute file end...
scan_end=47935
# Synchronisation variables...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 15 and 240 of the REAL grab(s)...
sync_point=128
sync_input="?"

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "zero_offset=$zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m " 
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to capture, (and store), the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 48000 bytes of random data.
   if [ $demo -eq 0 ]
   then
      # Use "sleep" to simulate a 1 second burst.
      sleep 1
      # "/dev/urandom is now used instead of RANDOM as it is MUCH faster.
      dd if=/dev/urandom of=/tmp/waveform.raw bs=48000 count=1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   # Now tested on PCLinuxOS 2009 and Debian 6.0.x.
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # Generate a smple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points.
# Defaults to OFF on the very first time run and must be manually enabled if needed.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section _is_ needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi

      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion set to $sync_point$synchronise..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 6 ]
   then
      printf "Zoom facility under construction..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# I have forced the use of UPPERCASE for the vast majority of the commands, so be aware!
# Incorrect commands are ignored and just reuns the scan and returns back to the COMMAND mode...
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured, (REAL scan), mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only, this disables the DRAW command.
   # Use DRAW to re-enable again. This is deliberate for slow machines...
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default, but with 10 sweeps...
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=10
      scan_end=47935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x and now PCLinuxOS 2009...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=6
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=60
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=600
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( 2 - $vert_shift ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and triggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise=" and OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=$[ ( $scan_start + 1 ) ]
      scan_jump=1
      scanloops=1
      subscript=$scan_start
      grab=0
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=0
         break
      fi
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger type, <CR> to disable:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         synchronise=", ON and fixed"
         trigger
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -eq $sync_point ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         synchronise=", ON and positive going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -lt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         synchronise=", ON and negative going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -gt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "EXT" ]
      then
         # Remember Corona688's code from the early stages of this thread...
         synchronise=", EXTERNAL and waiting"
         : # NOP... Place holder only.
      fi
      status=4
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   #
   # ******* Low signal level, ZOOM, facility. *******
   if [ "$kbinput" == "ZOOM" ]
   then
      status=6
      : # NOP... Place holder only.
      statusline
      sleep 2
   fi
   # ***** Low signal level, ZOOM, facility end. *****
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> .......................................... Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ........................................ Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "TRIG<CR> ........... Sets the synchronisation methods for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ .. Synchronise from a user variable fixed value only.\n"
   printf "        SubCommand: SYNCGT ............. Synchronise from a positive going edge.\n"
   printf "        SubCommand: SYNCLT ............. Synchronise from a negative going edge.\n"
   printf "        SubCommand: EXT ............................................ Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "ZOOM<CR> ......................... Unfinished, low signal level, ZOOM, facility.\n"
   printf "\n"
   printf "Manual here: <  http://wisecracker.host22.com/public/AudioScope_Manual.readme  >\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# This is the active part of the pseudo-synchroisation section.
trigger()
{
   while true
   do
      printf "\x1B[0;37;40m\x1B[20;14f"
      # This input method is something akin to BASIC's INKEY$...
      read -p "Sync point:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s sync_input
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$sync_input" == "" ]
      then
         break
      fi
      if [ "$sync_input" == "U" ]
      then
         sync_point=$[ ( $sync_point + 1 ) ]
      fi
      if [ "$sync_input" == "D" ]
      then
         sync_point=$[ ( $sync_point - 1 ) ]
      # Ensure the synchronisation point is NOT out of bounds.
      fi
      if [ $sync_point -ge 240 ]
      then
         sync_point=240
      fi
      if [ $sync_point -le 15 ]
      then
         sync_point=15
      fi
      printf "\x1B[23;3f Synchronisation point set to $sync_point...                                        "
   done
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Thu Jun 27, 2013 10:22 pm    Post subject: Reply with quote

Zoom for low signal levels is now complete.

It defaults to OFF and is never saved as part of the config file.
No user alterations are changed except switching from a real grab
to retrace mode.

From the command prompt window:-
ZOOM<CR>
(Then follow the on screen prompts.)

It has 5 depths:-
0) Default 8 bit to 4 bit quantising and uses the original plot.
1) X2, 7 bit to 4 bit quantising.
2) X4, 6 bit to 4 bit quantising.
3) X8, 5 bit to 4 bit quantising.
4) X16, direct bit for bit display.

How it works:-
Decimal 128 is considered to be the centre point of the sound card.
Therefore a balanced signal will be centred on this number.
The minimum most point at any zoom level is shifted to give a 0(ish)
value then anything above that is the remainder of the waveform.

To keep it within the 16 vertical characters the values are divided
by an order of 2^x depending upon the range.

None of the user coomands are available in this mode as it purely
to give an FSD for low and very low AC signal levels...

At the highest sensitivity, (4), centre point bit error will be
noticeable; this could be considered noise so be aware.

For those interested this is a _todo_ list:-

1) Horizontal shift control.
2) Basic frequency measurement.
3) Vertical claibration HW and SW in a similar guise to the built
in 1KHz sinewave generator.
4) DC input.
5) DC polarity.
6) Others, unknown at the moment.

Working on number 1) at the moment...

If anyone has any suggestions for any additions then please pass on
comments, all is welcome, even adverse ones...

This is now fast becoming a serious kids level application instead
of a fun project...

Enjoy...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Also to others on the same site for their input too.
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested in /dev/dsp mode on an Acer Aspire One netbook booting from a USB stick running PCLinuxOS 2009; also with
# the /dev/dsp sinewave generator enabled.
# Tested on all three in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# Relevant pointers to help:-
# http://wisecracker.host22.com/public/AudioScope_Manual.readme
# http://wisecracker.host22.com/public/cal_draw.jpg
# http://wisecracker.host22.com/public/cal_plot.jpg
# http://wisecracker.host22.com/public/mic_ear1.jpg
# http://wisecracker.host22.com/public/mic_ear2.jpg
# http://wisecracker.host22.com/public/mic_ear3.jpg
# http://wisecracker.host22.com/public/mic_ear4.jpg
#
# The latest vesrion will always be here:-
# http://www.unix.com/shell-programming-scripting/212939-start-simple-audio-scope-shell-script.html
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.88_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
# Default first time run capture mode, 0 = DEMO.
demo=0
# Draw proceedure mode, 0 = OFF
drawline=0
# Pseudo-continuous data file saving.
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number" and "char" are reusable variables...
count=0
number=0
char="?"
# Vertical components...
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
# Display setup...
graticule="Public Domain, 2013, B.Walker, G0LCU."
# Keyboard components...
kbinput="?"
tbinput=1
# "str_len" is a reusable variable IF required...
str_len=1
# "grab" is used for internal pseudo-synchronisation...
grab=0
# "sound_card_zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
sound_card_zero_offset=-2
# Zoom facility default status line.
zoom_facility="OFF"
zoom="Lowest sensitivity zoom/gain, default condition..."
# Horizontal components...
horiz=9
# Scan retraces...
scan=1
scanloops=1
# Timebase variable components...
subscript=0
# "scan_start" is from 0 to ( length of file - 64 )...
scan_start=0
# "scan_jump" is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# "scan_end" is at least 64 bytes in from the absolute file end...
scan_end=47935
# Synchronisation variables...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 15 and 240 of the REAL grab(s)...
sync_point=128
sync_input="?"

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "sound_card_zero_offset=$sound_card_zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m "
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to capture, (and store), the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 48000 bytes of random data.
   if [ $demo -eq 0 ]
   then
      # Use "sleep" to simulate a 1 second burst.
      sleep 1
      # "/dev/urandom is now used instead of RANDOM as it is MUCH faster.
      dd if=/dev/urandom of=/tmp/waveform.raw bs=48000 count=1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   # Now tested on PCLinuxOS 2009 and Debian 6.0.x.
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $sound_card_zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # Generate a simple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points.
# Defaults to OFF on the very first time run and must be manually enabled if needed.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section _is_ needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi
      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion set to $sync_point$synchronise..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 6 ]
   then
      printf "$zoom"
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# I have forced the use of UPPERCASE for the vast majority of the commands, so be aware!
# Incorrect commands are ignored and just reuns the scan and returns back to the COMMAND mode...
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured, (REAL scan), mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only, this disables the DRAW command.
   # Use DRAW to re-enable again. This is deliberate for slow machines...
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default, but with 10 sweeps...
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=10
      scan_end=47935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x and now PCLinuxOS 2009...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=6
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=60
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=600
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( 2 - $vert_shift ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and triggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise=" and OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=$[ ( $scan_start + 1 ) ]
      scan_jump=1
      scanloops=1
      subscript=$scan_start
      grab=0
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=0
         break
      fi
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger type, <CR> to disable:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         synchronise=", ON and fixed"
         trigger
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -eq $sync_point ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         synchronise=", ON and positive going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -lt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         synchronise=", ON and negative going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -gt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "EXT" ]
      then
         # Remember Corona688's code from the early stages of this thread...
         synchronise=", EXTERNAL and waiting"
         trigger
         : # NOP... Place holder only.
      fi
      status=4
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   #
   # ******* Low signal level, ZOOM, facility. *******
   if [ "$kbinput" == "ZOOM" ]
   then
      status=6
      hold=0
      zoom
      statusline
      read -p "Press <CR> to continue:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   fi
   # ***** Low signal level, ZOOM, facility end. *****
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> .......................................... Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ........................................ Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "TRIG<CR> ........... Sets the synchronisation methods for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ<CR> .. Synchronise from a variable, fixed value only.\n"
   printf "        SubCommand: SYNCGT<CR> ......... Synchronise from a positive going edge.\n"
   printf "        SubCommand: SYNCLT<CR> ......... Synchronise from a negative going edge.\n"
   printf "        SubCommand: EXT<CR> ........................................ Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "ZOOM<CR> ................................ Low signal level gain, ZOOM, facility.\n"
   printf "        SubCommand: 0<CR> ................. Default lowest zoom/gain capability.\n"
   printf "        SubCommand: 1<CR> ............................. X2 zoom/gain capability.\n"
   printf "        SubCommand: 2<CR> ............................. X4 zoom/gain capability.\n"
   printf "        SubCommand: 3<CR> ............................. X8 zoom/gain capability.\n"
   printf "        SubCommand: 4<CR> ............................ X16 zoom/gain capability.\n"
   printf "        SubCommand: <CR> ...... To exit zoom mode when waveform has been viewed.\n"
   printf "\n"
   printf "Manual here: <  http://wisecracker.host22.com/public/AudioScope_Manual.readme  >\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# This is the active part of the pseudo-synchroisation section.
trigger()
{
   while true
   do
      printf "\x1B[0;37;40m\x1B[20;14f"
      # This input method is something akin to BASIC's INKEY$...
      read -p "Sync point:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s sync_input
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$sync_input" == "" ]
      then
         break
      fi
      if [ "$sync_input" == "U" ]
      then
         sync_point=$[ ( $sync_point + 1 ) ]
      fi
      if [ "$sync_input" == "D" ]
      then
         sync_point=$[ ( $sync_point - 1 ) ]
      # Ensure the synchronisation point is NOT out of bounds.
      fi
      if [ $sync_point -ge 240 ]
      then
         sync_point=240
      fi
      if [ $sync_point -le 15 ]
      then
         sync_point=15
      fi
      printf "\x1B[23;3f Synchronisation point set to $sync_point...                                        "
   done
}

# #########################################################
# This is the software zooming facility.
# This does NOT alter any user values at all.
zoom()
{
   printf "\x1B[0;37;40m\x1B[20;14f"
   read -p "Set ZOOM gain, (4 = maximum sensitivity), 1, 2, 3 or 4<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
   zoom_facility="OFF"
   zoom="Lowest sensitivity zoom/gain, default condition..."
   # Written longhand for anyone to understnd how it works.
   if [ "$kbinput" == "1" ] || [ "$kbinput" == "2" ] || [ "$kbinput" == "3" ] || [ "$kbinput" == "4" ]
   then
      zoom_facility="ON"
   fi
   display
   # Just these four ranges are needed for the zoom facility.
   if [ "$zoom_facility" == "ON" ]
   then
      subscript=$scan_start
      vert_array=""
      for horiz in {9..72}
      do
         vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
         if [ "$kbinput" == "1" ]
         then
            zoom="\x1B[22;3f X2 zoom/gain condition..."
            vert=$[ ( $vert - 64 ) ]
            vert=$[ ( ( $vert / 8 ) + 2 ) ]
         fi
         if [ "$kbinput" == "2" ]
         then
            zoom="\x1B[22;3f X4 zoom/gain condition..."
            vert=$[ ( $vert - 96 ) ]
            vert=$[ ( ( $vert / 4 ) + 2 ) ]
         fi
         if [ "$kbinput" == "3" ]
         then
            zoom="\x1B[22;3f x8 zoom/gain condition..."
            vert=$[ ( $vert - 112 ) ]
            vert=$[ ( ( $vert / 2 ) + 2 ) ]
         fi
         if [ "$kbinput" == "4" ]
         then
            zoom="\x1B[22;3f X16 zoom/gain condition..."
            vert=$[ ( ( $vert - 120 ) + 2 ) ]
         fi
         if [ $vert -le 2 ]
         then
            vert=2
         fi
         if [ $vert -ge 17 ]
         then
            vert=17
         fi
         subscript=$[ ( $subscript + $scan_jump ) ]
         vert_array="$vert_array$vert "
         printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
      done
   fi
   # Revert to the plot function for the default lowest resolution.
   if [ "$zoom_facility" == "OFF" ]
   then
      plot
   fi
   draw
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Sun Jun 30, 2013 1:50 pm    Post subject: Reply with quote

Horizontal shift is now complete.

This is the last of the quick and easy parts of the code.

From now on the distance between uploads could be high as HW will be needed.
This has to be ludicrously simple so as to be built by a 10 year old.

The next upload will be the frequency counter needed for two parts of this
project. However this is a while away yet so now to desribe the X shift control.
(I WILL post a fully working Python version of a frequency counter I wrote ages
ago that uses /dev/dsp.)

Horizontal shift, from the cammand line window type:-

HSHIFT<CR>

Using the keys r, R, l, L, and Q or q change the position of the scan like this:-

r shifts scan to the right by one scan size, (64 bytes).
R shifts scan to the right by one byte at a time.
l shifts scan to the left by one scan size, (64 bytes).
R shifts scan to the left by one byte at a time.
Q or q exits this mode.

The keys respond like INKEY$ in BASIC...
No user values are changed except switching from real grab to rescan mode.
The TB speed will always be the fastest available although it could be made
variable if so desired. I decided against it as this is useful for searching
for odd wavefronts. The status line will let you know where in the file the
start of the current scan is...

Enjoy...

P.S. In the process of building a simple, starter, Y amplifier input ATM...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Also to others on the same site for their input too.
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested in /dev/dsp mode on an Acer Aspire One netbook booting from a USB stick running PCLinuxOS 2009; also with
# the /dev/dsp sinewave generator enabled.
# Tested on all three in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# Relevant pointers to help:-
# http://wisecracker.host22.com/public/AudioScope_Manual.readme
# http://wisecracker.host22.com/public/cal_draw.jpg
# http://wisecracker.host22.com/public/cal_plot.jpg
# http://wisecracker.host22.com/public/mic_ear1.jpg
# http://wisecracker.host22.com/public/mic_ear2.jpg
# http://wisecracker.host22.com/public/mic_ear3.jpg
# http://wisecracker.host22.com/public/mic_ear4.jpg
#
# The latest vesrion will always be here:-
# http://www.unix.com/shell-programming-scripting/212939-start-simple-audio-scope-shell-script.html
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.00.92_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
# Default first time run capture mode, 0 = DEMO.
demo=0
# Draw proceedure mode, 0 = OFF
drawline=0
# Pseudo-continuous data file saving.
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number", user and "char" are reusable, throw away variables...
user=0
count=0
number=0
char="?"
# Vertical components...
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
# Display setup...
graticule="Public Domain, 2013, B.Walker, G0LCU."
# Keyboard components...
kbinput="?"
tbinput=1
# "str_len" is a reusable variable IF required...
str_len=1
# "grab" is used for internal pseudo-synchronisation...
grab=0
# "sound_card_zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
sound_card_zero_offset=-2
# Zoom facility default status line.
zoom_facility="OFF"
zoom="Lowest sensitivity zoom/gain, default condition..."
# Horizontal components...
horiz=9
# Scan retraces...
scan=1
scanloops=1
# Timebase variable components...
subscript=0
# "scan_start" is from 0 to ( length of file - 64 )...
scan_start=0
# "scan_jump" is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# "scan_end" is at least 64 bytes in from the absolute file end...
scan_end=47935
# Synchronisation variables...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 15 and 240 of the REAL grab(s)...
sync_point=128
sync_input="?"

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "sound_card_zero_offset=$sound_card_zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m "
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to capture, (and store), the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 48000 bytes of random data.
   if [ $demo -eq 0 ]
   then
      # Use "sleep" to simulate a 1 second burst.
      sleep 1
      # "/dev/urandom is now used instead of RANDOM as it is MUCH faster.
      dd if=/dev/urandom of=/tmp/waveform.raw bs=48000 count=1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   # Now tested on PCLinuxOS 2009 and Debian 6.0.x.
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $sound_card_zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # Generate a simple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points.
# Defaults to OFF on the very first time run and must be manually enabled if needed.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section _is_ needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi
      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion set to $sync_point$synchronise..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 6 ]
   then
      printf "$zoom"
   fi
   if [ $status -eq 7 ]
   then
      printf "Horizontal shift, scan start at position $scan_start..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# I have forced the use of UPPERCASE for the vast majority of the commands, so be aware!
# Incorrect commands are ignored and just reuns the scan and returns back to the COMMAND mode...
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured, (REAL scan), mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only, this disables the DRAW command.
   # Use DRAW to re-enable again. This is deliberate for slow machines...
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default, but with 10 sweeps...
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=10
      scan_end=47935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x and now PCLinuxOS 2009...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=6
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=60
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=600
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( 2 - $vert_shift ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and triggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise=" and OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=$[ ( $scan_start + 1 ) ]
      scan_jump=1
      scanloops=1
      subscript=$scan_start
      grab=0
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=0
         break
      fi
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger type, <CR> to disable:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         synchronise=", ON and fixed"
         trigger
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -eq $sync_point ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         synchronise=", ON and positive going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -lt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         synchronise=", ON and negative going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -gt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "EXT" ]
      then
         # Remember Corona688's code from the early stages of this thread...
         synchronise=", EXTERNAL and waiting"
         trigger
         : # NOP... Place holder only.
      fi
      status=4
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   #
   # ******* Low signal level, ZOOM, facility. *******
   if [ "$kbinput" == "ZOOM" ]
   then
      status=6
      hold=0
      zoom
      statusline
      read -p "Press <CR> to continue:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   fi
   # ***** Low signal level, ZOOM, facility end. *****
   #
   # *********** Horizontal shift control. ***********
   if [ "$kbinput" == "HSHIFT" ]
   then
      status=7
      hold=0
      # These two variables stored to restore back to the user values...
      user=$scan_start
      count=$scan_jump
      # Temporarily fix the scan to start at the beginning at the fastest speed...
      scan_start=0
      scan_jump=1
      while true
      do
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Horizontal shift, press L, l, R, r, (Q or q to exit):- " -n 1 -s kbinput
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$kbinput" == "Q" ] || [ "$kbinput" == "q" ]
         then
            break
         fi
         if [ "$kbinput" == "L" ] || [ "$kbinput" == "l" ] || [ "$kbinput" == "R" ] || [ "$kbinput" == "r" ]
         then
            if [ "$kbinput" == "r" ]
            then
               scan_start=$[ ( $scan_start + 64 ) ]
            fi
            if [ "$kbinput" == "R" ]
            then
               scan_start=$[ ( $scan_start + 1 ) ]
            fi
            if [ "$kbinput" == "l" ]
            then
               scan_start=$[ ( $scan_start - 64 ) ]
            fi
            if [ "$kbinput" == "L" ]
            then
               scan_start=$[ ( $scan_start - 1 ) ]
            fi
            if [ $scan_start -le 0 ]
            then
               scan_start=0
            fi
            if [ $scan_start -ge $scan_end ]
            then
               scan_start=$scan_end
            fi
            display
            statusline
            plot
            draw
         fi
      done
      # User values restored back...
      scan_start=$user
      scan_jump=$count
   fi
   # ********* Horizontal shift control end. *********
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> .......................................... Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ........................................ Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "TRIG<CR> ........... Sets the synchronisation methods for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ<CR> .. Synchronise from a variable, fixed value only.\n"
   printf "        SubCommand: SYNCGT<CR> ......... Synchronise from a positive going edge.\n"
   printf "        SubCommand: SYNCLT<CR> ......... Synchronise from a negative going edge.\n"
   printf "        SubCommand: EXT<CR> ........................................ Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "ZOOM<CR> ................................ Low signal level gain, ZOOM, facility.\n"
   printf "        SubCommand: 0<CR> ................. Default lowest zoom/gain capability.\n"
   printf "        SubCommand: 1<CR> ............................. X2 zoom/gain capability.\n"
   printf "        SubCommand: 2<CR> ............................. X4 zoom/gain capability.\n"
   printf "        SubCommand: 3<CR> ............................. X8 zoom/gain capability.\n"
   printf "        SubCommand: 4<CR> ............................ X16 zoom/gain capability.\n"
   printf "        SubCommand: <CR> ...... To exit zoom mode when waveform has been viewed.\n"
   printf "HSHIFT<CR> ............ Shift the trace left or right at the highest scan speed.\n"
   printf "        SubCommand: L ........................ Shift the trace left by one byte.\n"
   printf "        SubCommand: l ... Shift the trace left by 64 bytes, (one complete scan).\n"
   printf "        SubCommand: R ....................... Shift the trace right by one byte.\n"
   printf "        SubCommand: r .. Shift the trace right by 64 bytes, (one complete scan).\n"
   printf "        SubCommand: Q or q ........ Exit back to normal usage, (quit this mode).\n"
   printf "Manual here: <  http://wisecracker.host22.com/public/AudioScope_Manual.readme  >\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# This is the active part of the pseudo-synchroisation section.
trigger()
{
   while true
   do
      printf "\x1B[0;37;40m\x1B[20;14f"
      # This input method is something akin to BASIC's INKEY$...
      read -p "Sync point:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s sync_input
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$sync_input" == "" ]
      then
         break
      fi
      if [ "$sync_input" == "U" ]
      then
         sync_point=$[ ( $sync_point + 1 ) ]
      fi
      if [ "$sync_input" == "D" ]
      then
         sync_point=$[ ( $sync_point - 1 ) ]
      # Ensure the synchronisation point is NOT out of bounds.
      fi
      if [ $sync_point -ge 240 ]
      then
         sync_point=240
      fi
      if [ $sync_point -le 15 ]
      then
         sync_point=15
      fi
      printf "\x1B[23;3f Synchronisation point set to $sync_point...                                        "
   done
}

# #########################################################
# This is the software zooming facility.
# This does NOT alter any user values at all.
zoom()
{
   printf "\x1B[0;37;40m\x1B[20;14f"
   read -p "Set ZOOM gain, (4 = maximum sensitivity), 1, 2, 3 or 4<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
   zoom_facility="OFF"
   zoom="Lowest sensitivity zoom/gain, default condition..."
   # Written longhand for anyone to understnd how it works.
   if [ "$kbinput" == "1" ] || [ "$kbinput" == "2" ] || [ "$kbinput" == "3" ] || [ "$kbinput" == "4" ]
   then
      zoom_facility="ON"
   fi
   display
   # Just these four ranges are needed for the zoom facility.
   if [ "$zoom_facility" == "ON" ]
   then
      subscript=$scan_start
      vert_array=""
      for horiz in {9..72}
      do
         vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
         if [ "$kbinput" == "1" ]
         then
            zoom="\x1B[22;3f X2 zoom/gain condition..."
            vert=$[ ( $vert - 64 ) ]
            vert=$[ ( ( $vert / 8 ) + 2 ) ]
         fi
         if [ "$kbinput" == "2" ]
         then
            zoom="\x1B[22;3f X4 zoom/gain condition..."
            vert=$[ ( $vert - 96 ) ]
            vert=$[ ( ( $vert / 4 ) + 2 ) ]
         fi
         if [ "$kbinput" == "3" ]
         then
            zoom="\x1B[22;3f x8 zoom/gain condition..."
            vert=$[ ( $vert - 112 ) ]
            vert=$[ ( ( $vert / 2 ) + 2 ) ]
         fi
         if [ "$kbinput" == "4" ]
         then
            zoom="\x1B[22;3f X16 zoom/gain condition..."
            vert=$[ ( ( $vert - 120 ) + 2 ) ]
         fi
         if [ $vert -le 2 ]
         then
            vert=2
         fi
         if [ $vert -ge 17 ]
         then
            vert=17
         fi
         subscript=$[ ( $subscript + $scan_jump ) ]
         vert_array="$vert_array$vert "
         printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
      done
   fi
   # Revert to the plot function for the default lowest resolution.
   if [ "$zoom_facility" == "OFF" ]
   then
      plot
   fi
   draw
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Sat Jul 13, 2013 5:56 pm    Post subject: Reply with quote

Now added a RESET command, many thanks to Don Cragun for the help.

Also rearranged the internal HELP file.

Also added placeholders ready for the Frequency Counter to be added.

The RESET command returns to terminal back to the default colours, clears the window, deletes all files relevant to the code, resets the terminal and reloads the AudioScope.sh script.

It does NOT delete dynamically saved grabs, (that is using the SAVEON command), but all saved variables via the AudioScope.config file WILL be lost...

This is good for testing as well as for user problems that may occur...

Enjoy...

Bazza...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Also to "Don Cragun" and others on the same site for their input too.
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested in /dev/dsp mode on an Acer Aspire One netbook booting from a USB stick running PCLinuxOS 2009; also with
# the /dev/dsp sinewave generator enabled.
# Tested on all three in DEMO mode.
#
# Added the first simple circuit at the end of this script.
#
# Relevant pointers to help:-
# http://wisecracker.host22.com/public/AudioScope_Manual.readme
# http://wisecracker.host22.com/public/cal_draw.jpg
# http://wisecracker.host22.com/public/cal_plot.jpg
# http://wisecracker.host22.com/public/mic_ear1.jpg
# http://wisecracker.host22.com/public/mic_ear2.jpg
# http://wisecracker.host22.com/public/mic_ear3.jpg
# http://wisecracker.host22.com/public/mic_ear4.jpg
#
# The latest vesrion will always be here:-
# http://www.unix.com/shell-programming-scripting/212939-start-simple-audio-scope-shell-script.html
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again. To quit this script
# and close the window just press Ctrl-C. This generator will be needed for the calibration of some timebase ranges.
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'data="\\\\x80\\\\x26\\\\x00\\\\x26\\\\x7F\\\\xD9\\\\xFF\\\\xD9"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# Variables in use.
ifs_str=$IFS
version="           \$VER: AudioScope.sh_Version_0.01.00_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
# Default first time run capture mode, 0 = DEMO.
demo=0
# Draw proceedure mode, 0 = OFF
drawline=0
# Pseudo-continuous data file saving.
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number", user and "char" are reusable, throw away variables...
user=0
count=0
number=0
char="?"
# Vertical components...
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
# Display setup...
graticule="Public Domain, 2013, B.Walker, G0LCU."
# Keyboard components...
kbinput="?"
tbinput=1
# "str_len" is a reusable variable IF required...
str_len=1
# "grab" is used for internal pseudo-synchronisation...
grab=0
# "sound_card_zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
sound_card_zero_offset=-2
# Zoom facility default status line.
zoom_facility="OFF"
zoom="Lowest sensitivity zoom/gain, default condition..."
# Horizontal components...
horiz=9
# Scan retraces...
scan=1
scanloops=1
# Timebase variable components...
subscript=0
# "scan_start" is from 0 to ( length of file - 64 )...
scan_start=0
# "scan_jump" is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# "scan_end" is at least 64 bytes in from the absolute file end...
scan_end=47935
# Synchronisation variables...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 15 and 240 of the REAL grab(s)...
sync_point=128
sync_input="?"

# #########################################################
# Add the program tilte to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope.\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "sound_card_zero_offset=$sound_card_zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m "
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to capture, (and store), the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 48000 bytes of random data.
   if [ $demo -eq 0 ]
   then
      # Use "sleep" to simulate a 1 second burst.
      sleep 1
      # "/dev/urandom is now used instead of RANDOM as it is MUCH faster.
      dd if=/dev/urandom of=/tmp/waveform.raw bs=48000 count=1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   # Now tested on PCLinuxOS 2009 and Debian 6.0.x.
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $sound_card_zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # Generate a simple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points.
# Defaults to OFF on the very first time run and must be manually enabled if needed.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section _is_ needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi
      fi
   IFS=$ifs_str
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running $scan of $scanloops scans..."
   fi
   if [ $status -eq 2 ]
   then
      printf "Running in single shot storage mode..."
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion set to $sync_point$synchronise..."
   fi
   if [ $status -eq 5 ]
   then
      printf "CAUTION, AUTO-SAVING FACILITY ENABLED!!!"
   fi
   if [ $status -eq 6 ]
   then
      printf "$zoom"
   fi
   if [ $status -eq 7 ]
   then
      printf "Horizontal shift, scan start at position $scan_start..."
   fi
   if [ $status -eq 8 ]
   then
      printf "Assessing the frequnency of a symmetrical waveform, PLEASE WAIT..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# I have forced the use of UPPERCASE for the vast majority of the commands, so be aware!
# Incorrect commands are ignored and just reuns the scan and returns back to the COMMAND mode...
kbcommands()
{
   IFS=$ifs_str
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured, (REAL scan), mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only, this disables the DRAW command.
   # Use DRAW to re-enable again. This is deliberate for slow machines...
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default, but with 10 sweeps...
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=10
      scan_end=47935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x and now PCLinuxOS 2009...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=6
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=60
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=600
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( 2 - $vert_shift ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and triggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise=" and OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=$[ ( $scan_start + 1 ) ]
      scan_jump=1
      scanloops=1
      subscript=$scan_start
      grab=0
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=0
         break
      fi
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger type, <CR> to disable:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         synchronise=", ON and fixed"
         trigger
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -eq $sync_point ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         synchronise=", ON and positive going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -lt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         synchronise=", ON and negative going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -gt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "EXT" ]
      then
         # Remember Corona688's code from the early stages of this thread...
         synchronise=", EXTERNAL and waiting"
         trigger
         : # NOP... Place holder only.
      fi
      status=4
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   #
   # ******* Low signal level, ZOOM, facility. *******
   if [ "$kbinput" == "ZOOM" ]
   then
      status=6
      hold=0
      zoom
      statusline
      read -p "Press <CR> to continue:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   fi
   # ***** Low signal level, ZOOM, facility end. *****
   #
   # *********** Horizontal shift control. ***********
   if [ "$kbinput" == "HSHIFT" ]
   then
      status=7
      hold=0
      # These two variables stored to restore back to the user values...
      user=$scan_start
      count=$scan_jump
      # Temporarily fix the scan to start at the beginning at the fastest speed...
      scan_start=0
      scan_jump=1
      while true
      do
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Horizontal shift, press L, l, R, r, (Q or q to exit):- " -n 1 -s kbinput
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$kbinput" == "Q" ] || [ "$kbinput" == "q" ]
         then
            break
         fi
         if [ "$kbinput" == "L" ] || [ "$kbinput" == "l" ] || [ "$kbinput" == "R" ] || [ "$kbinput" == "r" ]
         then
            if [ "$kbinput" == "r" ]
            then
               scan_start=$[ ( $scan_start + 64 ) ]
            fi
            if [ "$kbinput" == "R" ]
            then
               scan_start=$[ ( $scan_start + 1 ) ]
            fi
            if [ "$kbinput" == "l" ]
            then
               scan_start=$[ ( $scan_start - 64 ) ]
            fi
            if [ "$kbinput" == "L" ]
            then
               scan_start=$[ ( $scan_start - 1 ) ]
            fi
            if [ $scan_start -le 0 ]
            then
               scan_start=0
            fi
            if [ $scan_start -ge $scan_end ]
            then
               scan_start=$scan_end
            fi
            display
            statusline
            plot
            draw
         fi
      done
      # User values restored back...
      scan_start=$user
      scan_jump=$count
   fi
   # ********* Horizontal shift control end. *********
   #
   # ** Symmetrical waveform frequency measurement. **
   if [ "$kbinput" == "FREQ" ]
   then
      status=8
      : # NOP... Place holder only.
      statusline
      sleep 2
   fi
   # Symmetrical waveform frequency measurement end. *
   #
   # **** Rerun, (RESET), the AudioScope script. *****
   if [ "$kbinput" == "RESET" ]
   then
      # Reset terminal back to normal...
      printf "\x1B[0m"
      clear
      # Delete all unwanted files, ignore ANY error reports for missing files...
      # Note that all saved grabs using "SAVEON" are left intact.
      rm /tmp/AudioScope.config
      rm /tmp/sinewave.raw
      rm /tmp/1KHz-Test.sh
      rm /tmp/waveform.raw
      reset
      exec ~/AudioScope.sh "$@"
   fi
   # ************* RESET capability end. *************
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> .......................................... Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ........................................ Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "TRIG<CR> ........... Sets the synchronisation methods for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ<CR> .. Synchronise from a variable, fixed value only.\n"
   printf "        SubCommand: SYNCGT<CR> ......... Synchronise from a positive going edge.\n"
   printf "        SubCommand: SYNCLT<CR> ......... Synchronise from a negative going edge.\n"
   printf "        SubCommand: EXT<CR> ........................................ Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "ZOOM<CR> ................................ Low signal level gain, ZOOM, facility.\n"
   printf "        SubCommand: 0<CR> ................. Default lowest zoom/gain capability.\n"
   printf "        SubCommand: 1<CR> ............................. X2 zoom/gain capability.\n"
   printf "        SubCommand: 2<CR> ............................. X4 zoom/gain capability.\n"
   printf "        SubCommand: 3<CR> ............................. X8 zoom/gain capability.\n"
   printf "        SubCommand: 4<CR> ............................ X16 zoom/gain capability.\n"
   printf "        SubCommand: <CR> ...... To exit zoom mode when waveform has been viewed.\n"
   printf "HSHIFT<CR> ............ Shift the trace left or right at the highest scan speed.\n"
   printf "        SubCommand: L ........................ Shift the trace left by one byte.\n"
   printf "        SubCommand: l ... Shift the trace left by 64 bytes, (one complete scan).\n"
   printf "        SubCommand: R ....................... Shift the trace right by one byte.\n"
   printf "        SubCommand: r .. Shift the trace right by 64 bytes, (one complete scan).\n"
   printf "        SubCommand: Q or q ........ Exit back to normal usage, (quit this mode).\n"
   printf "Manual here: <  http://wisecracker.host22.com/public/AudioScope_Manual.readme  >\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "RESET<CR> ............................ Do a complete COLD restart of the script.\n"
   printf "FREQ<CR> ..... Measure a symmetrical waveform's frequency, accuracy 0.1 percent.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# This is the active part of the pseudo-synchroisation section.
trigger()
{
   while true
   do
      printf "\x1B[0;37;40m\x1B[20;14f"
      # This input method is something akin to BASIC's INKEY$...
      read -p "Sync point:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s sync_input
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$sync_input" == "" ]
      then
         break
      fi
      if [ "$sync_input" == "U" ]
      then
         sync_point=$[ ( $sync_point + 1 ) ]
      fi
      if [ "$sync_input" == "D" ]
      then
         sync_point=$[ ( $sync_point - 1 ) ]
      # Ensure the synchronisation point is NOT out of bounds.
      fi
      if [ $sync_point -ge 240 ]
      then
         sync_point=240
      fi
      if [ $sync_point -le 15 ]
      then
         sync_point=15
      fi
      printf "\x1B[23;3f Synchronisation point set to $sync_point...                                        "
   done
}

# #########################################################
# This is the software zooming facility.
# This does NOT alter any user values at all.
zoom()
{
   printf "\x1B[0;37;40m\x1B[20;14f"
   read -p "Set ZOOM gain, (4 = maximum sensitivity), 1, 2, 3 or 4<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
   zoom_facility="OFF"
   zoom="Lowest sensitivity zoom/gain, default condition..."
   # Written longhand for anyone to understnd how it works.
   if [ "$kbinput" == "1" ] || [ "$kbinput" == "2" ] || [ "$kbinput" == "3" ] || [ "$kbinput" == "4" ]
   then
      zoom_facility="ON"
   fi
   display
   # Just these four ranges are needed for the zoom facility.
   if [ "$zoom_facility" == "ON" ]
   then
      subscript=$scan_start
      vert_array=""
      for horiz in {9..72}
      do
         vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
         if [ "$kbinput" == "1" ]
         then
            zoom="\x1B[22;3f X2 zoom/gain condition..."
            vert=$[ ( $vert - 64 ) ]
            vert=$[ ( ( $vert / 8 ) + 2 ) ]
         fi
         if [ "$kbinput" == "2" ]
         then
            zoom="\x1B[22;3f X4 zoom/gain condition..."
            vert=$[ ( $vert - 96 ) ]
            vert=$[ ( ( $vert / 4 ) + 2 ) ]
         fi
         if [ "$kbinput" == "3" ]
         then
            zoom="\x1B[22;3f x8 zoom/gain condition..."
            vert=$[ ( $vert - 112 ) ]
            vert=$[ ( ( $vert / 2 ) + 2 ) ]
         fi
         if [ "$kbinput" == "4" ]
         then
            zoom="\x1B[22;3f X16 zoom/gain condition..."
            vert=$[ ( ( $vert - 120 ) + 2 ) ]
         fi
         if [ $vert -le 2 ]
         then
            vert=2
         fi
         if [ $vert -ge 17 ]
         then
            vert=17
         fi
         subscript=$[ ( $subscript + $scan_jump ) ]
         vert_array="$vert_array$vert "
         printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
      done
   fi
   # Revert to the plot function for the default lowest resolution.
   if [ "$zoom_facility" == "OFF" ]
   then
      plot
   fi
   draw
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue and white wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
Bazza
LXF regular


Joined: Sat Mar 21, 2009 11:16 am
Posts: 1473
Location: Loughborough

PostPosted: Sun Nov 10, 2013 12:42 pm    Post subject: Reply with quote

Major update this time guys and gals.

Version now set at 0.20.01.

Frequency Counter added for the symmetrical waveforms sine, square, triangle, (and maybe sawtooth).
This is for the future addition of the DC component and measures from 50Hz to 3500Hz to within 0.1% accuracy.
In DEMO mode this will always read 500Hz as that is the file manually generated for the task.

Code now added for the creation of running files ready for the vertical calibration.

Note, that the vertical amplifier and calbrator are built and the circuit for the calibrator is adeed to the
end of the script.

The Windows version of the vertical calibrator SW works as a genuine file under Windows but as this is generated
on the fly it has NOT been transfered and tested yet. Feedback would be most welcome on this one. It should give
a 1KHz tone for around 8 seconds ONLY and has to be rerun ATM...

Enjoy this latest update...

Bazza...
Code:

#!/bin/bash
#
# AudioScope.sh
#
# IMPORTANT!!! This code assumes that it is saved as AudioScope.sh inside your _home_ drawer...
# Set the permissions to YOUR requirements and launch the code using the following:-
#
# Your Prompt> ./AudioScope.sh<CR>
#
# At this point I will include and say thank you to "Corona688", a member of http://www.unix.com for his input...
# Also to "Don Cragun" and others on the same site for their input too.
# Many thanks also go to the guys who have helped with this on http://www.linuxformat.com for all your input too...
#
# Tested in SOX mode on this Macbook Pro 13 inch, OSX 10.7.5 with the SOX sinewave generator enabled.
# Tested in /dev/dsp mode on an aging HP notebook running Debian 6.0.x with the /dev/dsp sinewave generator enabled.
# Tested in /dev/dsp mode on an Acer Aspire One netbook booting from a USB stick running PCLinuxOS 2009; also with
# the /dev/dsp sinewave generator enabled.
# Tested on all three in DEMO mode.
#
# Added the first simple circuit at the end of this script.
# Added the second simple circuit at the end of this script.
#
# Relevant pointers to help:-
# http://wisecracker.host22.com/public/AudioScope_Manual.readme
# http://wisecracker.host22.com/public/cal_draw.jpg
# http://wisecracker.host22.com/public/cal_plot.jpg
# http://wisecracker.host22.com/public/mic_ear1.jpg
# http://wisecracker.host22.com/public/mic_ear2.jpg
# http://wisecracker.host22.com/public/mic_ear3.jpg
# http://wisecracker.host22.com/public/mic_ear4.jpg
# More photos to follow.
#
# The latest version will always be here:-
# http://www.unix.com/shell-programming-scripting/212939-start-simple-audio-scope-shell-script.html
#
# NOTE TO SELF:- Remove "/tmp" and replace with "~" when ready, AND, "/tmp" is automatically cleared on this machine per reboot.

# #########################################################
# Variables in use.
ifs_str="$IFS"
ver="0.20.01"
version="           \$VER: AudioScope.sh_Version_"$ver"_PD_B.Walker_G0LCU.           "
setup=" Please wait while the very first scan and configuration file is generated. "
# Default first time run capture mode, 0 = DEMO.
demo=0
# Draw proceedure mode, 0 = OFF
drawline=0
# Pseudo-continuous data file saving.
savefile="0000000000"
save_string="OFF"
# "hold" and "status" will always be reset to "1" on program exit.
hold=1
status=1
# "count", "number", "user", "char" are reusable, throw away variables...
user=0
count=0
number=0
char="?"
# Vertical components...
# vert_one and vert_two are the vertical plotting points for the draw() function...
vert_one=2
vert_two=2
vert=12
vert_shift=2
vshift="?"
vert_array=""
vert_draw=9
# Display setup...
graticule="Public Domain, 2013, B.Walker, G0LCU."
# Keyboard components...
kbinput="?"
tbinput=1
# "str_len" is a reusable variable IF required...
str_len=1
# "grab" is used for internal pseudo-synchronisation...
grab=0
# "sound_card_zero_offset" can only be manually changed in the AudioScope.config file, OR, here...
sound_card_zero_offset=-2
# Zoom facility default status line.
zoom_facility="OFF"
zoom="Lowest sensitivity zoom/gain, default condition..."
# Horizontal components...
horiz=9
# Scan retraces...
scan=1
scanloops=1
# Timebase variable components...
subscript=0
# "scan_start" is from 0 to ( length of file - 64 )...
scan_start=0
# "scan_jump" is from 1 to ( ( ( scan_end - scan_start ) / 64) + 1 )...
scan_jump=1
# "scan_end" is at least 64 bytes in from the absolute file end...
scan_end=47935
# Synchronisation variables...
# synchronise switches the syncchroisation ON or OFF...
synchronise="OFF"
# sync_point is any value between 15 and 240 of the REAL grab(s)...
sync_point=128
sync_input="?"
wave_form=0
freq_array=""
data="\\x80\\x26\\x00\\x26\\x7F\\xD9\\xFF\\xD9"
# Generate an 65536 byte raw 1KHz sinewave file from "data"...
> /tmp/sinewave.raw
chmod 644 /tmp/sinewave.raw
for wave_form in {0..8191}
do
        printf "$data" >> /tmp/sinewave.raw
done
data="\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF"
# Generate an 8000 byte raw 500Hz squarewave file for DEMO mode from "data"...
> /tmp/squarewave.raw
chmod 644 /tmp/squarewave.raw
for wave_form in {0..499}
do
        printf "$data" >> /tmp/squarewave.raw
done
# Generate a first copy of "waveform.raw" for this script.
cp /tmp/squarewave.raw /tmp/waveform.raw
chmod 644 /tmp/waveform.raw
> /tmp/symmetricalwave.raw
chmod 644 /tmp/symmetricalwave.raw

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments and then EDIT the line pointing to the correct </Users/barrywalker/Downloads/sox-14.4.0/> to use it.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds and then re-runs. To quit this script and close the window just press and hold Ctrl-C until the
# program exits. This generator will be needed for the calibration of some timebase ranges.
#
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf 'printf "\x1B]0;1KHz Sinewave Generator.\x07"\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        clear\n' >> /tmp/1KHz-Test.sh
#printf '        printf "\nPRESS AND HOLD Ctrl-C UNTIL EXITED...\n"\n' >> /tmp/1KHz-Test.sh
#printf '        /Users/barrywalker/Downloads/sox-14.4.0/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to "xterm", will generate a new shell script and execute it in a new xterm terminal...
# Just EDIT out the comments to use it.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz sinewave in a separate window
# that lasts for 8 seconds and then re-runs. To quit this script and close the window just press and hold Ctrl-C until the
# program exits. This generator will be needed for the calibration of some timebase ranges.
#
#> /tmp/1KHz-Test.sh
#chmod 744 /tmp/1KHz-Test.sh
#printf '#!/bin/bash\n' >> /tmp/1KHz-Test.sh
#printf 'printf "\x1B]0;1KHz Sinewave Generator.\x07"\n' >> /tmp/1KHz-Test.sh
#printf 'while true\n' >> /tmp/1KHz-Test.sh
#printf 'do\n' >> /tmp/1KHz-Test.sh
#printf '        clear\n' >> /tmp/1KHz-Test.sh
#printf '        printf "\nPRESS AND HOLD Ctrl-C UNTIL EXITED...\n"\n' >> /tmp/1KHz-Test.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/1KHz-Test.sh
#printf 'done\n' >> /tmp/1KHz-Test.sh
#sleep 1
#xterm -e /tmp/1KHz-Test.sh &

# #########################################################
# This section is for future usage only at this point.
# It contains the running scripts for vertical calibration
# For *NIX and Linux flavours plus Windows XP, Vista and Windows 7.
# #########################################################
# FOR Windows SOund eXchange USERS ONLY!!!         IMPRTANT:- UNTESTED AT THE MOMENT!!!
# NOTE:- The code itself DOES work but generating it on the fly has NOT been tested yet.
# Windows batch file square wave generator using SOund eXchange, SOX.
# Just TRANSFER the file /tmp/VERT_BAT.BAT to a Windows machine and run from Windows Command Prompt.
# You WILL need to change the absolute path on the last line for your SOX installation.
# It is in uncommented mode so that anyone interested can experiment _immediatey_.
> /tmp/VERT_BAT.BAT
echo -e -n '@ECHO OFF\r\n' >> /tmp/VERT_BAT.BAT
echo -e -n 'CLS\r\n' >> /tmp/VERT_BAT.BAT
echo -e -n 'SET "rawfile=\xFF\xFF\xFF\xFF\x01\x01\x01\x01"\r\n' >> /tmp/VERT_BAT.BAT
echo -e -n 'ECHO | SET /P="%rawfile%" > %TEMP%.\\SQ-WAVE.RAW\r\n' >> /tmp/VERT_BAT.BAT
echo -e -n 'FOR /L %%n IN (1,1,13) DO TYPE %TEMP%.\\SQ-WAVE.RAW >> %TEMP%.\\SQ-WAVE.RAW\r\n' >> /tmp/VERT_BAT.BAT
echo -e -n 'C:\\PROGRA~1\\SOX-14-4-1\\SOX -b 8 -r 8000 -e unsigned-integer -c 1 %TEMP%.\\SQ-WAVE.RAW -d\r\n' >> /tmp/VERT_BAT.BAT

# #########################################################
# FOR SOund eXchance USERS ONLY!!!        TESTED!!!
# The lines below, from ">" to the last "printf", will generate a new shell script...
# Just EDIT out the comments and then EDIT the line pointing to the correct </full/path/to/sox/> to use it.
# TRANSFER this file to another remote machine that has SOund eXchange, SOX, installed.
# It assumes that you have SoX installed. When this script is run it generates a 1KHz squarewave on a remote computer
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again.
# To quit this script just press Ctrl-C. This generator will be needed for the vertical calibration.
# Don't forget to chmod "VERT_SOX.sh" when copied onto the remote machine.
#> /tmp/VERT_SOX.sh
#printf '#!/bin/bash\n' >> /tmp/VERT_SOX.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/VERT_SOX.sh
#printf 'data="\\\\xFF\\\\xFF\\\\xFF\\\\xFF\\\\x00\\\\x00\\\\x00\\\\x00"\n' >> /tmp/VERT_SOX.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/VERT_SOX.sh
#printf 'do\n' >> /tmp/VERT_SOX.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/VERT_SOX.sh
#printf 'done\n' >> /tmp/VERT_SOX.sh
#printf 'while true\n' >> /tmp/VERT_SOX.sh
#printf 'do\n' >> /tmp/VERT_SOX.sh
#printf '        /full/path/to/sox/play -b 8 -r 8000 -e unsigned-integer /tmp/sinewave.raw\n' >> /tmp/VERT_SOX.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/VERT_SOX.sh
#printf 'done\n' >> /tmp/VERT_SOX.sh

# #########################################################
# FOR /dev/dsp USERS ONLY!!!           TESTED!!!
# The lines below, from ">" to the last "printf", will generate a new shell script...
# Just EDIT out the comments to use it. TRANSFER this file to another machine that has the /dev/dsp device.
# It assumes that you have /dev/dsp _installed_. When this script is run it generates a 1KHz squarewave on a remote computer
# that lasts for 8 seconds. Just press ENTER when this window is active and it will repeat again.
# To quit this script just press Ctrl-C. This generator will be needed for the vertical calibration.
# Don't forget to chmod "VERT_DSP.sh" when copied onto the remote machine.
#> /tmp/VERT_DSP.sh
#printf '#!/bin/bash\n' >> /tmp/VERT_DSP.sh
#printf '> /tmp/sinewave.raw\n' >> /tmp/VERT_DSP.sh
#printf 'data="\\\\xFF\\\\xFF\\\\xFF\\\\xFF\\\\x00\\\\x00\\\\x00\\\\x00"\n' >> /tmp/1KHz-Test.sh
#printf 'for waveform in {0..8191}\n' >> /tmp/VERT_DSP.sh
#printf 'do\n' >> /tmp/VERT_DSP.sh
#printf '        printf "$data" >> /tmp/sinewave.raw\n' >> /tmp/VERT_DSP.sh
#printf 'done\n' >> /tmp/VERT_DSP.sh
#printf 'while true\n' >> /tmp/VERT_DSP.sh
#printf 'do\n' >> /tmp/VERT_DSP.sh
#printf '        cat /tmp/sinewave.raw > /dev/dsp\n' >> /tmp/VERT_DSP.sh
#printf '        read -p "Press ENTER to rerun OR Ctrl-C to quit:- " -e kbinput\n' >> /tmp/VERT_DSP.sh
#printf 'done\n' >> /tmp/VERT_DSP.sh

# #########################################################
# Add the program tilte and version to the Terminal title bar...
# This may NOT work in every Terminal so just comment it out if it doesn't.
printf "\x1B]0;Shell AudioScope, version "$ver".\x07"

# #########################################################
# Generate a config file and temporarily store inside /tmp
if [ -f /tmp/AudioScope.config ]
then
   . /tmp/AudioScope.config
else
   user_config
fi
user_config()
{
   > /tmp/AudioScope.config
   chmod 644 /tmp/AudioScope.config
   printf "demo=$demo\n" >> /tmp/AudioScope.config
   printf "drawline=$drawline\n" >> /tmp/AudioScope.config
   printf "hold=1\n" >> /tmp/AudioScope.config
   printf "status=1\n" >> /tmp/AudioScope.config
   printf "sound_card_zero_offset=$sound_card_zero_offset\n" >> /tmp/AudioScope.config
   printf "scanloops=$scanloops\n" >> /tmp/AudioScope.config
   printf "scan_start=$scan_start\n" >> /tmp/AudioScope.config
   printf "scan_jump=$scan_jump\n" >> /tmp/AudioScope.config
   printf "scan_end=$scan_end\n" >> /tmp/AudioScope.config
   printf "vert_shift=$vert_shift\n" >> /tmp/AudioScope.config
   printf "setup='$setup'\n" >> /tmp/AudioScope.config
   printf "save_string='$save_string'\n" >> /tmp/AudioScope.config
}

# #########################################################
# Screen display setup function.
display()
{
   # Set foregound and background graticule colours and foreground and background other window colours.
   printf "\x1B[0;36;44m"
   clear
   graticule="       +-------+-------+-------+---[\x1B[0;37;44mDISPLAY\x1B[0;36;44m]---+-------+-------+--------+       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"     0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+ <     \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       |       |       |       |       +       |       |       |        |       \n"
   graticule=$graticule"       +-------+-------+-------+-------+-------+-------+-------+--------+       \n"
   graticule=$graticule" \x1B[0;37;40m+-----------------------------[COMMAND  WINDOW]------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| COMMAND:-                                                                  |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+------------------------------[STATUS WINDOW]-------------------------------+\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m| Stopped...                                                                 |\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m|$setup|\x1B[0;37;44m \n"
   graticule=$graticule" \x1B[0;37;40m+----------------------------------------------------------------------------+\x1B[0;37;44m "
   printf "$graticule"
   # Set the colours for plotting.
   printf "\x1B[1;37;44m"
}

# #########################################################
# Pick which method to capture, (and store), the waveform on the fly.
waveform()
{
   > /tmp/waveform.raw
   chmod 644 /tmp/waveform.raw
   # Demo mode, generate 48000 bytes of random data.
   if [ $demo -eq 0 ]
   then
      # Use "sleep" to simulate a 1 second burst.
      sleep 1
      # "/dev/urandom is now used instead of RANDOM as it is MUCH faster.
      dd if=/dev/urandom of=/tmp/waveform.raw bs=48000 count=1
   fi
   # Using the aging(/old) /dev/dsp device, mono, 8 bits per sample and 8KHz sampling rate, 8000 unsigned-integer bytes of data...
   # Now tested on PCLinuxOS 2009 and Debian 6.0.x.
   if [ $demo -eq 1 ]
   then
      # This uses the oss-compat installation from your distro's repository...
      dd if=/dev/dsp of=/tmp/waveform.raw bs=8000 count=1
   fi
   # The main means of obtaining the unsigned-integer data, using SoX, (Sound eXcahnge) from http://sox.sourceforge.net ...
   if [ $demo -eq 2 ]
   then
      # Change the absolute address for your location of "sox"...
      /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 48000 -b 8 -c 1 -e unsigned-integer -> /tmp/waveform.raw trim 0 00:01
   fi
}

# #########################################################
# Plot the points inside the window...
plot()
{
   subscript=$scan_start
   vert_array=""
   for horiz in {9..72}
   do
      vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
      # Add a small offset to give a straight line with zero input allowing for mid-point sound card bit error.
      vert=$[ ( $vert + $sound_card_zero_offset ) ]
      if [ $vert -le 0 ]
      then
         vert=0
      fi
      if [ $vert -ge 255 ]
      then
         vert=255
      fi
      # Pseudo-vertical shift of + or - 1 vertical division maximum.
      vert=$[ ( ( $vert / 16 ) + $vert_shift ) ]
      # Ensure the plot is NOT out of bounds after moving the shift position.
      if [ $vert -le 2 ]
      then
         vert=2
      fi
      if [ $vert -ge 17 ]
      then
         vert=17
      fi
      subscript=$[ ( $subscript + $scan_jump ) ]
      # Generate a simple space delimited 64 sample array.
      vert_array="$vert_array$vert "
      printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This function connects up the plotted points.
# Defaults to OFF on the very first time run and must be manually enabled if needed.
draw()
{
   statusline
   IFS=" "
   subscript=0
   number=0
   vert_one=2
   vert_two=2
   vert_draw=( $vert_array )
   for horiz in {9..71}
   do
      # Obtain the two vertical components.
      vert_one=${vert_draw[ $subscript ]}
      subscript=$[ ( $subscript + 1 ) ]
      vert_two=${vert_draw[ $subscript ]}
      # Now subtract them and obtain an absolute value - ALWAYS 0 to positive...
      number=$[ ( $vert_two - $vert_one ) ]
      number=${number#-}
      # This decision section _is_ needed.
      if [ $number -le 1 ]
      then
         : # NOP. Do nothing...
      fi
      # This section does the drawing...
      if [ $number -ge 2 ]
      then
         if [ $vert_one -gt $vert_two ]
         then
            vert_one=$[ ( $vert_one - 1 ) ]
            while [ $vert_one -gt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one - 1 ]
            done
         fi
         if [ $vert_two -gt $vert_one ]
         then
            vert_one=$[ ( $vert_one + 1 ) ]
            while [ $vert_one -lt $vert_two ]
            do
               printf "\x1B[1;37;44m\x1B["$vert_one";"$horiz"f*"
               vert_one=$[ $vert_one + 1 ]
            done
         fi
      fi
   IFS="$ifs_str"
   done
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# This is the information line _parser_...
statusline()
{
   printf "\x1B[0;37;40m\x1B[22;3f                                                                            \x1B[22;4f"
   if [ $status -eq 0 ]
   then
      printf "Stopped..."
   fi
   if [ $status -eq 1 ]
   then
      printf "Running \x1B[0;32;40m$scan\x1B[0;37;40m of \x1B[0;32;40m$scanloops\x1B[0;37;40m scan(s)..."
   fi
   if [ $status -eq 2 ]
   then
      printf "\x1B[0;32;40mRunning in single shot storage mode...\x1B[0;37;40m"
   fi
   if [ $status -eq 3 ]
   then
      printf "Drawing the scan..."
   fi
   if [ $status -eq 4 ]
   then
      printf "Synchroniastion set to \x1B[0;32;40m$sync_point$synchronise\x1B[0;37;40m..."
   fi
   if [ $status -eq 5 ]
   then
      printf "\x1B[1;31;40mCAUTION, AUTO-SAVING FACILITY ENABLED!!!\x1B[0;37;40m"
   fi
   if [ $status -eq 6 ]
   then
      printf "$zoom"
   fi
   if [ $status -eq 7 ]
   then
      printf "Horizontal shift, scan start at position \x1B[0;32;40m$scan_start\x1B[0;37;40m..."
   fi
   if [ $status -eq 8 ]
   then
      printf "Symmetrical waveform frequency is \x1B[0;32;40m"$count"\x1B[0;37;40m Hz..."
   fi
   if [ $status -eq 254 ]
   then
      status=1
      setup=$version
      printf "\x1B[23;3f$setup"
   fi
   # Set end of plot to COMMAND window.
   printf "\x1B[0;37;40m\x1B[20;14f"
}

# #########################################################
# All keyboard commands appear here when the scanning stops; there will be lots of them to make subtle changes...
# I have forced the use of UPPERCASE for the vast majority of the commands, so be aware!
# Incorrect commands are ignored and just reuns the scan and returns back to the COMMAND mode...
kbcommands()
{
   IFS="$ifs_str"
   status=1
   scan=1
   read -p "Press <CR> to (re)run, HELP or QUIT<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[20;14f"
   # Rerun scans captured or stored.
   if [ "$kbinput" == "" ]
   then
      status=1
      statusline
   fi
   # Run scans in captured, (REAL scan), mode only.
   if [ "$kbinput" == "RUN" ]
   then
      status=1
      hold=1
      statusline
   fi
   # Swtich off capture mode and rerun one storage shot only, this disables the DRAW command.
   # Use DRAW to re-enable again. This is deliberate for slow machines...
   if [ "$kbinput" == "HOLD" ]
   then
      drawline=0
      status=2
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # Quit the program.
   if [ "$kbinput" == "QUIT" ]
   then
      status=255
      break
   fi
   # Display the _online_ HELP file in default terminal colours.
   if [ "$kbinput" == "HELP" ]
   then
      status=0
      scanloops=1
      hold=0
      commandhelp
   fi
   # Enable DEMO pseudo-capture mode, default, but with 10 sweeps...
   if [ "$kbinput" == "DEMO" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=10
      scan_end=47935
      demo=0
      hold=1
      statusline
      sleep 1
   fi
   # Enable /dev/dsp capture mode, if your Linux flavour does NOT have it, install oss-compat from the distro's repository.
   # This is the mode used to test on Debian 6.0.x and now PCLinuxOS 2009...
   if [ "$kbinput" == "DSP" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=7935
      hold=1
      demo=1
      statusline
      sleep 1
   fi
   # Eable SOX capture mode, this code is designed around this application on a Macbook Pro 13 inch OSX 10.7.5...
   if [ "$kbinput" == "SOX" ]
   then
      status=1
      scan_start=0
      scan_jump=1
      scanloops=1
      scan_end=47935
      hold=1
      demo=2
      statusline
      sleep 1
   fi
   # The next three commands set the timebase scans; 1, 10 or 100 before COMMAND mode is re-enabled and can be used.
   if [ "$kbinput" == "ONE" ]
   then
      status=1
      scanloops=1
      hold=1
   fi
   if [ "$kbinput" == "TEN" ]
   then
      status=1
      scanloops=10
      hold=1
   fi
   if [ "$kbinput" == "HUNDRED" ]
   then
      status=1
      scanloops=100
      hold=1
   fi
   if [ "$kbinput" == "VER" ]
   then
      status=254
   fi
   # ************ Horizontal components. *************
   # ************ User timebase section. *************
   # Written longhand for kids to understand.
   if [ "$kbinput" == "TBVAR" ]
   then
      # Ensure capture mode is turned off.
      # RUN<CR> will re-enable it if required.
      scanloops=1
      status=1
      hold=0
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase starting point. From 0 to $scan_end<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Ensure the timebase values are set to default before changing.
      scan_start=0
      scan_jump=1
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_start=0
         tbinput=0
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan start point.
         if [ $number -le 47 ]
         then
            scan_start=0
            tbinput=0
         fi
         if [ $number -ge 58 ]
         then
            scan_start=0
            tbinput=0
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_start" variable.
      scan_start=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_start -le 0 ]
      then
         scan_start=0
      fi
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=$scan_end
      fi
      # Use exactly the same method as above to determine the jump interval.
      # Now set the jump interval, this is the scan speed...
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set timebase user speed. From 1 to $[ ( ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ) ]<CR> " -e tbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      # Eliminate any keyboard error longhand...
      # Ensure a NULL string does NOT exist.
      if [ "$tbinput" == "" ]
      then
         scan_jump=1
         tbinput=1
      fi
      # Find the length of the inputted string.
      str_len=`printf "${#tbinput}"`
      # Set the string to the correct last position for the _subscript_ point.
      str_len=$[ ( $str_len - 1 ) ]
      # Now check for continuous numerical charaters ONLY.
      for count in $( seq 0 $str_len )
      do
         # Reuse variable _number_ to obtain each character per loop.
         number=`printf "${tbinput:$count:1}"`
         # Now convert the character to a decimal number.
         number=`printf "%d" \'$number`
         # IF ANY ASCII character exists that is not numerical then reset the scan jump value.
         if [ $number -le 47 ]
         then
            scan_jump=1
            tbinput=1
         fi
         if [ $number -ge 58 ]
         then
            scan_jump=1
            tbinput=1
         fi
      done
      # If all is OK pass the "tbinput" value into the "scan_jump" variable.
      scan_jump=$tbinput
      # Do a final check that the number is not out of bounds.
      if [ $scan_jump -le 1 ]
      then
         scan_jump=1
      fi
      # Reuse number for upper limit...
      number=$[ ( ( ( $scan_end - $scan_start ) / 64 ) + 1 ) ]
      if [ $scan_jump -ge $number ]
      then
         scan_jump=$number
      fi
      printf "\x1B[0;37;40m\x1B[22;4fScan start at offset $scan_start, with a jump rate of $scan_jump."
      sleep 1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   # ********** User timebase section end. ***********
   # ********* Calibrated timebase section. **********
   if [ "$kbinput" == "FASTEST" ]
   then
      scan_start=0
      scan_jump=1
      setup=" Uncalibrated horizontal scan, vertical and storage modes, AC coupled only. "
   fi
   if [ "$kbinput" == "1mS" ]
   then
      scan_start=0
      setup=" 1mS/DIV, uncalibrated vertical and storage modes, AC coupled only.         "
      if [ $demo -eq 0 ]
      then
         scan_jump=6
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=1
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=6
      fi
   fi
   if [ "$kbinput" == "10mS" ]
   then
      scan_start=0
      setup=" 10mS/DIV, uncalibrated vertical and storage modes, AC coupled only.        "
      if [ $demo -eq 0 ]
      then
         scan_jump=60
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=10
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=60
      fi
   fi
   if [ "$kbinput" == "100mS" ]
   then
      scan_start=0
      setup=" 100mS/DIV, uncalibrated vertical and storage modes, AC coupled only.       "
      if [ $demo -eq 0 ]
      then
         scan_jump=600
      fi
      if [ $demo -eq 1 ]
      then
         scan_jump=100
      fi
      if [ $demo -eq 2 ]
      then
         scan_jump=600
      fi
   fi
   # *********** Calibrated timebase end. ************
   #
   # ************* Vertical components. **************
   # ******** Pseudo-vertical shift control. *********
   if [ "$kbinput" == "SHIFT" ]
   then
      while true
      do
         scanloops=1
         status=1
         hold=0
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Vertical shift:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s vshift
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$vshift" == "" ]
         then
            break
         fi
         if [ "$vshift" == "D" ]
         then
            vert_shift=$[ ( $vert_shift + 1 ) ]
         fi
         if [ "$vshift" == "U" ]
         then
            vert_shift=$[ ( $vert_shift - 1 ) ]
         # Ensure the shift psoition is NOT out of bounds.
         fi
         if [ $vert_shift -ge 6 ]
         then
            vert_shift=6
         fi
         if [ $vert_shift -le -2 ]
         then
            vert_shift=-2
         fi
         printf "\x1B[23;3f Vertical shift is $[ ( 2 - $vert_shift ) ] from the mid-point position...                        "
      done
   fi
   # ****** Pseudo-vertical shift control end. *******
   # ********** Connect all plotted points. **********
   if [ "$kbinput" == "DRAW" ]
   then
      drawline=1
      status=3
      hold=0
      scanloops=1
      statusline
      sleep 1
   fi
   # ************* Connected plots done. *************
   #
   # **** PSEUDO synchronisation and triggering. ****
   if [ "$kbinput" == "TRIG" ]
   then
      synchronise=" and OFF"
      sync_point=128
      status=0
      hold=0
      scan_start=$[ ( $scan_start + 1 ) ]
      scan_jump=1
      scanloops=1
      subscript=$scan_start
      grab=0
      if [ $scan_start -ge $scan_end ]
      then
         scan_start=0
         break
      fi
      printf "\x1B[0;37;40m\x1B[20;14f"
      read -p "Set trigger type, <CR> to disable:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$kbinput" == "SYNCEQ" ]
      then
         synchronise=", ON and fixed"
         trigger
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -eq $sync_point ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCGT" ]
      then
         synchronise=", ON and positive going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -lt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "SYNCLT" ]
      then
         synchronise=", ON and negative going"
         for subscript in $( seq $scan_start $scan_end )
         do
            grab=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
            if [ $grab -gt 128 ]
            then
               scan_start=$subscript
               break
            fi
         done
      fi
      if [ "$kbinput" == "EXT" ]
      then
         # Remember Corona688's code from the early stages of this thread...
         synchronise=", EXTERNAL and waiting"
         trigger
         : # NOP... Place holder only.
      fi
      status=4
      statusline
      sleep 1
   fi
   # ** PSEUDO synchronisation and triggering end. ***
   #
   # ************* Auto-saving facility. *************
   if [ "$kbinput" == "SAVEON" ]
   then
      status=5
      save_string="ON"
      statusline
      sleep 2
   fi
   if [ "$kbinput" == "SAVEOFF" ]
   then
      status=1
      save_string="OFF"
      statusline
   fi
   # *********** Auto-saving facility end. ***********
   #
   # ******* Low signal level, ZOOM, facility. *******
   if [ "$kbinput" == "ZOOM" ]
   then
      status=6
      hold=0
      zoom
      statusline
      read -p "Press <CR> to continue:- " -e kbinput
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 "
   fi
   # ***** Low signal level, ZOOM, facility end. *****
   #
   # *********** Horizontal shift control. ***********
   if [ "$kbinput" == "HSHIFT" ]
   then
      status=7
      hold=0
      # These two variables stored to restore back to the user values...
      user=$scan_start
      count=$scan_jump
      # Temporarily fix the scan to start at the beginning at the fastest speed...
      scan_start=0
      scan_jump=1
      while true
      do
         printf "\x1B[0;37;40m\x1B[20;14f"
         # This input method is something akin to BASIC's INKEY$...
         read -p "Horizontal shift, press L, l, R, r, (Q or q to exit):- " -n 1 -s kbinput
         printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
         if [ "$kbinput" == "Q" ] || [ "$kbinput" == "q" ]
         then
            break
         fi
         if [ "$kbinput" == "L" ] || [ "$kbinput" == "l" ] || [ "$kbinput" == "R" ] || [ "$kbinput" == "r" ]
         then
            if [ "$kbinput" == "r" ]
            then
               scan_start=$[ ( $scan_start + 64 ) ]
            fi
            if [ "$kbinput" == "R" ]
            then
               scan_start=$[ ( $scan_start + 1 ) ]
            fi
            if [ "$kbinput" == "l" ]
            then
               scan_start=$[ ( $scan_start - 64 ) ]
            fi
            if [ "$kbinput" == "L" ]
            then
               scan_start=$[ ( $scan_start - 1 ) ]
            fi
            if [ $scan_start -le 0 ]
            then
               scan_start=0
            fi
            if [ $scan_start -ge $scan_end ]
            then
               scan_start=$scan_end
            fi
            display
            statusline
            plot
            draw
         fi
      done
      # User values restored back...
      scan_start=$user
      scan_jump=$count
      statusline
      sleep 1
   fi
   # ********* Horizontal shift control end. *********
   #
   # ** Symmetrical waveform frequency measurement. **
   if [ "$kbinput" == "FREQ" ]
   then
      status=8
      hold=0
      freq_counter
      statusline
      sleep 2
   fi
   # Symmetrical waveform frequency measurement end. *
   #
   # **** Rerun, (RESET), the AudioScope script. *****
   if [ "$kbinput" == "RESET" ]
   then
      # Reset terminal back to normal...
      printf "\x1B[0m"
      clear
      # Delete all unwanted files, ignore ANY error reports for missing files...
      # Note that all saved grabs using "SAVEON" are left intact.
      rm /tmp/AudioScope.config
      rm /tmp/sinewave.raw
      rm /tmp/squarewave.raw
      rm /tmp/symmetricalwave.raw
      rm /tmp/waveform.raw
      rm /tmp/1KHz-Test.sh
      reset
      # IMPORTANT!!! ENSURE, AudioScope.sh is inside your _home_ drawer.
      exec ~/AudioScope.sh "$@"
   fi
   # ************* RESET capability end. *************
   statusline
}

# #########################################################
# Help clears the screen to the startup defaults and prints command line help...
commandhelp()
{
   status=2
   hold=0
   printf "\x1B[0m"
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "<CR> ................................................. Reruns the scan(s) again.\n"
   printf "RUN<CR> ......................... Reruns the scan(s), always with real captures.\n"
   printf "QUIT<CR> .................................................... Quits the program.\n"
   printf "HELP<CR> ................................................ This help as required.\n"
   printf "HOLD<CR> ........................................ Switch to pseudo-storage mode.\n"
   printf "DEMO<CR> .......... Switch capture to default DEMO mode and 10 continuous scans.\n"
   printf "DSP<CR> ...................... Switch capture to Linux /dev/dsp mode and 1 scan.\n"
   printf "SOX<CR> ....... Switch capture to multi-platform SOund eXchange mode and 1 scan.\n"
   printf "ONE<CR> ......................................... Sets the number of scans to 1.\n"
   printf "TEN<CR> ........................................ Sets the number of scans to 10.\n"
   printf "HUNDRED<CR> ............. Sets the number of scans to 100, (not very practical).\n"
   printf "VER<CR> .................. Displays the version number inside the status window.\n"
   printf "TBVAR<CR> ............ Set up uncalibrated user timebase offset and jump points.\n"
   printf "        SubCommands: ............................. Follow the on screen prompts.\n"
   printf "FASTEST<CR> .................. Set all modes to the fastest possible scan speed.\n"
   printf "1mS<CR> .......................................... Set scanning rate to 1mS/DIV.\n"
   printf "10mS<CR> ........................................ Set scanning rate to 10mS/DIV.\n"
   printf "100mS<CR> ...................................... Set scanning rate to 100mS/DIV.\n"
   printf "SHIFT<CR> ............ Set the vertical position from -4 to +4 to the mid-point.\n"
   printf "        SubCommands: ............ Press U or D then <CR> when value is obtained.\n"
   printf "DRAW<CR> .......... Connect up each vertical plot to give a fully lined display.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "TRIG<CR> ........... Sets the synchronisation methods for storage mode retraces.\n"
   printf "        SubCommand: SYNCEQ<CR> .. Synchronise from a variable, fixed value only.\n"
   printf "        SubCommand: SYNCGT<CR> ......... Synchronise from a positive going edge.\n"
   printf "        SubCommand: SYNCLT<CR> ......... Synchronise from a negative going edge.\n"
   printf "        SubCommand: EXT<CR> ........................................ Unfinished.\n"
   printf "SAVEON<CR> .................... Auto-saves EVERY scan with a numerical filename.\n"
   printf "SAVEOFF<CR> ....................................... Disables auto-save facility.\n"
   printf "ZOOM<CR> ................................ Low signal level gain, ZOOM, facility.\n"
   printf "        SubCommand: 0<CR> ................. Default lowest zoom/gain capability.\n"
   printf "        SubCommand: 1<CR> ............................. X2 zoom/gain capability.\n"
   printf "        SubCommand: 2<CR> ............................. X4 zoom/gain capability.\n"
   printf "        SubCommand: 3<CR> ............................. X8 zoom/gain capability.\n"
   printf "        SubCommand: 4<CR> ............................ X16 zoom/gain capability.\n"
   printf "        SubCommand: <CR> ...... To exit zoom mode when waveform has been viewed.\n"
   printf "HSHIFT<CR> ............ Shift the trace left or right at the highest scan speed.\n"
   printf "        SubCommand: L ........................ Shift the trace left by one byte.\n"
   printf "        SubCommand: l ... Shift the trace left by 64 bytes, (one complete scan).\n"
   printf "        SubCommand: R ....................... Shift the trace right by one byte.\n"
   printf "        SubCommand: r .. Shift the trace right by 64 bytes, (one complete scan).\n"
   printf "        SubCommand: Q or q ........ Exit back to normal usage, (quit this mode).\n"
   printf "Manual here: <  http://wisecracker.host22.com/public/AudioScope_Manual.readme  >\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   clear
   printf "CURRENT COMMANDS AVAILABLE:-\n"
   printf "RESET<CR> ............................ Do a complete COLD restart of the script.\n"
   printf "FREQ<CR> ..... Measure a symmetrical waveform's frequency, accuracy 0.1 percent.\n"
   printf "\n"
   read -p "Press <CR> to continue:- " -e kbinput
   display
   statusline
}

# #########################################################
# This is the active part of the pseudo-synchroisation section.
trigger()
{
   while true
   do
      printf "\x1B[0;37;40m\x1B[20;14f"
      # This input method is something akin to BASIC's INKEY$...
      read -p "Sync point:- U for up 1, D for down 1, <CR> to RETURN:- " -n 1 -s sync_input
      printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
      if [ "$sync_input" == "" ]
      then
         break
      fi
      if [ "$sync_input" == "U" ]
      then
         sync_point=$[ ( $sync_point + 1 ) ]
      fi
      if [ "$sync_input" == "D" ]
      then
         sync_point=$[ ( $sync_point - 1 ) ]
      # Ensure the synchronisation point is NOT out of bounds.
      fi
      if [ $sync_point -ge 240 ]
      then
         sync_point=240
      fi
      if [ $sync_point -le 15 ]
      then
         sync_point=15
      fi
      printf "\x1B[23;3f Synchronisation point set to $sync_point...                                        "
   done
}

# #########################################################
# This is the software zooming facility.
# This does NOT alter any user values at all.
zoom()
{
   printf "\x1B[0;37;40m\x1B[20;14f"
   read -p "Set ZOOM gain, (4 = maximum sensitivity), 1, 2, 3 or 4<CR> " -e kbinput
   printf "\x1B[0;37;40m\x1B[20;14f                                                                 \x1B[0;37;40m\x1B[20;14f"
   zoom_facility="OFF"
   zoom="Lowest sensitivity zoom/gain, default condition..."
   # Written longhand for anyone to understnd how it works.
   if [ "$kbinput" == "1" ] || [ "$kbinput" == "2" ] || [ "$kbinput" == "3" ] || [ "$kbinput" == "4" ]
   then
      zoom_facility="ON"
   fi
   display
   # Just these four ranges are needed for the zoom facility.
   if [ "$zoom_facility" == "ON" ]
   then
      subscript=$scan_start
      vert_array=""
      for horiz in {9..72}
      do
         vert=`hexdump -n1 -s$subscript -v -e '1/1 "%u"' /tmp/waveform.raw`
         if [ "$kbinput" == "1" ]
         then
            zoom="\x1B[22;3f X2 zoom/gain condition..."
            vert=$[ ( $vert - 64 ) ]
            vert=$[ ( ( $vert / 8 ) + 2 ) ]
         fi
         if [ "$kbinput" == "2" ]
         then
            zoom="\x1B[22;3f X4 zoom/gain condition..."
            vert=$[ ( $vert - 96 ) ]
            vert=$[ ( ( $vert / 4 ) + 2 ) ]
         fi
         if [ "$kbinput" == "3" ]
         then
            zoom="\x1B[22;3f x8 zoom/gain condition..."
            vert=$[ ( $vert - 112 ) ]
            vert=$[ ( ( $vert / 2 ) + 2 ) ]
         fi
         if [ "$kbinput" == "4" ]
         then
            zoom="\x1B[22;3f X16 zoom/gain condition..."
            vert=$[ ( ( $vert - 120 ) + 2 ) ]
         fi
         if [ $vert -le 2 ]
         then
            vert=2
         fi
         if [ $vert -ge 17 ]
         then
            vert=17
         fi
         subscript=$[ ( $subscript + $scan_jump ) ]
         vert_array="$vert_array$vert "
         printf "\x1B[1;37;44m\x1B["$vert";"$horiz"f*"
      done
   fi
   # Revert to the plot function for the default lowest resolution.
   if [ "$zoom_facility" == "OFF" ]
   then
      plot
   fi
   draw
}

# #########################################################
# Frequency counter from 50Hz to 3500Hz.
freq_counter()
{
IFS=" "
count=0
freq_array=""
subscript=0
user=0
# This is a demo mode so that there is no need to access HW.
> /tmp/symmetricalwave.raw
if [ $demo -eq 0 ]
then
   sleep 1
   cp /tmp/squarewave.raw /tmp/symmetricalwave.raw
fi
# These two are for real grabs
if [ $demo -eq 1 ]
then
   dd if=/dev/dsp of=/tmp/symmetricalwave.raw bs=8000 count=1
fi
if [ $demo -eq 2 ]
then
   # You WILL need to change your absolute path for your version of SOX...
   /Users/barrywalker/Downloads/sox-14.4.0/sox -q -V0 -d -t raw -r 8000 -b 8 -c 1 -e unsigned-integer -> /tmp/symmetricalwave.raw trim 0 00:01
fi
user=`hexdump -v -e '1/1 "%u "' /tmp/symmetricalwave.raw`
freq_array=($user)
while true
do
   # Assume a square wave "mark to space" ratio of 1 to 1 is used,
   # then "wait" until a "space" is found.
   # (For those that don't know.)
   #
   #                  +------+      +---
   # Square wave:-    | Mark |Space |
   #               ---+      +------+
   #
   # This ensures that the loop cycles when NO input is
   # applied to the microphone socket.
   # Exit this loop when "mark" is found or n >= 8000...
   while [ ${freq_array[$subscript]} -ge 128 ]
   do
      subscript=$[ ( $subscript + 1 ) ]
      # Ensure as soon as subscript >= 8000 occurs it drops out of the loop.
      if [ $subscript -ge 8000 ]
      then
         break
      fi
   done
   # Ensure as soon as subscript >= 8000 occurs it drops completely out of this loop.
   if [ $subscript -ge 8000 ]
   then
      break
   fi
   # Now the "mark" can loop until a "space" is found again and the whole
   # can cycle until subscript >= 8000...
   while [ ${freq_array[$subscript]} -le 127 ]
   do
      subscript=$[ ( $subscript + 1 ) ]
      # Ensure as soon as subscript >= 8000 occurs it drops out of the loop.
      if [ $subscript -ge 8000 ]
      then
         break
      fi
   done
   # Ensure as soon as subscript >= 8000 occurs it drops completely out of this loop.
   if [ $subscript -ge 8000 ]
   then
      break
   fi
   # "count" will become the frequency of a symmetrical waveform
   # when the above loops are finally exited, subscript >= 8000...
   # Tick up the freq(uency) per "mark to space" cycle.
   count=$[ ( $count + 1 ) ]
   done
IFS="$ifs_str"
}

# #########################################################
# Do an initial screen set up...
display
statusline
setup=$version

# #########################################################
# This is the main loop...
while true
do
   for scan in $( seq 1 $scanloops )
   do
      # "hold" determines a new captured scan or retrace of an existing scan...
      if [ $hold -eq 1 ]
      then
         waveform
      fi
      display
      statusline
      plot
      if [ $drawline -eq 1 ]
      then
         draw
      fi
      if [ "$save_string" == "ON" ]
      then
         savefile=`date +%s`
         cp /tmp/waveform.raw /tmp/$savefile
      fi
   done
   status=0
   statusline
   kbcommands
done

# #########################################################
# Getout, autosave AudioScope.config, cleanup and quit...
if [ $status -eq 255 ]
then
   # Save the user configuration file.
   user_config
   # Remove "Shell AudioScope" from the title bar.
   printf "\x1B]0;\x07"
   sleep 0.1
   # Reset back to normal...
   printf "\x1B[0m"
   clear
   reset
fi
printf "\nProgram terminated...\n\nTerminal reset back to startup defaults...\n\n"

# #########################################################
# The FIRST extremely simple construction part.
# This is a simple I/O board for testing for the Macbook Pro 13 inch...
# It is just as easy to replace the 4 pole 3.5mm Jack Plug with 2 x 3.5mm Stereo Jack
# Plugs for machines with separate I/O sockets.
#                                                       Orange.       White flylead.
# Tip ----->  O  <------------------------------------+---------O <----------+--------+
# Ring 1 -->  H  <-------------------------+-----------)--------O <- Blue.   |        |
# Ring 2 -->  H  <--------------+-----+-----)----------)--------O <- Yellow. |        |
# _Gnd_ --->  H  <----+         |  C1 | +  |          |         O <- Green.  |        |
#           +===+     |         \   =====  \          \         |            \        |
#           |   |     |         /   --+--  /          /         |            /        |
#        P1 |   |     |         \     |    \          \         |            \        |
#           |   |     |      R1 /     | R2 /       R3 /         |         R4 /        |
#            \ /      |         \     |    \          \         |            \        |
#             H       |         /     |    /          /         |            /        |
#            ~~~      |         |     |    |          |         |            |        |
#                     +---------+------)---+----------+---------+------------+        |
# Pseudo-Ground. -> __|__             |                                               |
#                   /////             +-----------------------------------------------+
# Parts List:-
# P1 ......... 3.5mm, 4 pole jack plug.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2, R3 ..... 33R, 1/8W, 5% tolerence resistor.
# R4 ......... 1M, 1/8W, 5% tolerence resistor.
# C1 ......... 47uF, 16V electrolytic.
# 4 way terminal block.
# Stripboard, (Verobaord), as required.
# Green, yellow, orange, blue, white and tinned copper wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# Crimp terminal, 1 off, optional.
# #########################################################
# #########################################################
# The SECOND extremely simple construction part.
# This is the simple vertical calibration HW for this project.
# This uses the dedicated square wave generators for remote machine usage.
# This circuit is isolated from the computer through a transformer.
#                                   R1        1.4VP-P       R2      R3  1VP-P
# Left Channel O/P. O----+    +---/\/\/\---+-----O--------/\/\/\--/\/\/\--O T2
# Tip of 4 pole plug.    | T1 |            |   T1|  0.1VP-P R4      R5    |
#                        |    |            |     |  T3 O--/\/\/\--/\/\/\--+
#                         )||(             |     |     |    R6      R7 10mVP-P
#                         )||(          D1 | +   |     +--/\/\/\--/\/\/\--O T4
#                         )||( Primary.  --+-- ,-+-,        R8      R9    |
#              Secondary. )||(o (CT)      / \   \ /    +--/\/\/\--/\/\/\--+
#                         )||(           '-+-' --+--   |
#                         )||(             |  D2 | +   |
#                         )||(             |     |     |
#                        |    |            |     |     |
# Barrel of 4 pole plug. |    |            |     |     |           O/P Common.
# Pseudo-Ground. -> O--+-+    +------------+-----+-----+------------------O T5
#                    __|__
#                    /////
# Test lead red wire.
# Connect to T1 - T4 <-----------------------------( Red Croc Clip.
# Test lead black wire.
#      Connect to T5 <-----------------------------( Black Croc Clip.
# Parts List:-
# T1 ......... Audio Output Transformer, example, Maplin P/No:- LB14Q.
# D1, D2 ..... 1N4148, silicon small signal diodes.
# R1 ......... 2K2, 1/8W, 5% tolerence resistor.
# R2 ......... 12K, 1/8W, 5% tolerence resistor.
# R3 ......... 1K5, 1/8W, 5% tolerence resistor.
# R4 ......... 27K, 1/8W, 5% tolerence resistor.
# R5 ......... 3K3, 1/8W, 5% tolerence resistor.
# R6 ......... 2K7, 1/8W, 5% tolerence resistor.
# R7, R8 ..... 330R, 1/8W, 5% tolerence resistor.
# R9 ......... 4R7, 1/8W, 5% tolerence resistor, this can be omitted.
# T1 - T5 .... 5 way terminal block.
# Stripboard, (Verobaord), as required.
# Red, black and tinned copper wire as required.
# Small cable ties, optional.
# Stick on cable clip, optional.
# 1 Red and 1 Black Croc clip(s) for the test lead.
# #########################################################

_________________
73...

Bazza, G0LCU...

Team AMIGA...
Back to top
View user's profile Send private message
towy71
Moderator


Joined: Wed Apr 06, 2005 3:11 pm
Posts: 4257
Location: wild West Wales

PostPosted: Mon Nov 11, 2013 7:20 pm    Post subject: Reply with quote

Eek 1373 lines of code, shouldn't that be on github or something Wink
_________________
still looking for that door into summer
Back to top
View user's profile Send private message
View previous topic :: View next topic  
Display posts from previous:   
Post new topic   Reply to topic    Linux Format forums Forum Index -> Programming All times are GMT
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Linux Format forums topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group


Copyright 2011 Future Publishing, all rights reserved.


Web hosting by UKFast